【发布时间】:2021-11-08 03:45:27
【问题描述】:
我想为我们的 REST API 实现一个自定义的反序列化器,它不仅被 Java 应用程序使用。因此我不想让 Jackson 将类型信息放入序列化的 JSON 中。
我目前正在努力反序列化 CollectionExpand,因为它包含特定 ResourceModel 的列表 data。
public class EntityModel<R extends ResourceModel> implements Serializable {
private R data;
private List<ResourceLink> links;
private List<CollectionExpand> expands;
}
public class CollectionExpand {
private String name;
// Resource Model is an interface
private Collection<ResourceModel> data;
}
ResourceModel 是一个接口,每个CollectionExpand 包含一个ResourceModel 每个name 类型的集合。
例如,json 输出可能如下所示。
{
"data": {},
"links": [],
"expand": [
{
"name": "photos",
"data": [
{
"id": 12,
"name": "hello.jpg"
},
{
"id": 12,
"name": "hello.jpg"
}
]
},
{
"name": "persons",
"data": [
{
"id": 783378,
"name": "Peter",
"age": 12
},
{
"id": 273872,
"name": "Maria",
"age": 77
}
]
}
]
}
如您所见,每个名称都包含相同类型的资源模型。 photos 包含 PhotoResourceModel 和 person 包含 PersonResourceModel。
我开始实现我的自定义 Jackson Deserializer
public class CollectionExpandDeserializer extends StdDeserializer<CollectionExpand> {
public CollectionExpandDeserializer() {
super(CollectionExpand.class);
}
@Override
public CollectionExpand deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
CollectionExpand collectionExpand = new CollectionExpand();
if (Objects.equals(p.nextFieldName(), "name")) {
collectionExpand.setName(p.nextTextValue());
}
if (Objects.equals(p.nextFieldName(), "data")) {
// depending on the field name I would like to delegate the deserialization to a specific type.
if (name.equals("photos") {
// how to do this?
collectionExpand.setData(/* deserialize to a list of PhotoResource */);
}
}
return collectionExpand;
}
我目前不知道如何委派告诉 Jackson 将其反序列化为 PhotoResource 列表。
一般来说,这是正确的方法还是有其他方法(在序列化时不将任何 Jackson 元数据放入 JSON)?
【问题讨论】:
-
我在使用 C# 的项目中遇到了类似的问题。您可以使用的另一种解决方法(我知道它值得畏惧,但它有效)是定义一个自定义类型,将每个具体类型存储为一个单独的集合,您可以定义映射器方法,让您在两种形式之间进行转换。此方法依赖于类型匹配。
-
@OmarAbdelBari 感谢您的评论。问题是我需要将数据反序列化回现有类。没有机会改变结构。
标签: java jackson deserialization json-deserialization