gpt4 book ai didi

json - Jackson 多态反序列化和序列化

转载 作者:行者123 更新时间:2023-12-05 02:01:25 33 4
gpt4 key购买 nike

我将分别调用两种不同类型。我想根据业务需求进行反序列化或序列化。

一种类型的json:

{
"type": "foo",
"data": [{
"someCommonProperty": "common property",
"fooProperty": "foo specific property"
},{
"someCommonProperty": "common property1",
"fooProperty": "foo specific property1"
}]
}

另一种json:

{
"type": "bar",
"data": [{
"someCommonProperty": "common property",
"barProperty": "bar specific property",
"type": "type1"
},{
"someCommonProperty": "common property1",
"barProperty": "bar specific property1",
"type": "type1"
}]
}

我有如下类(class)

 public class Parent {

private String type;

@JsonTypeInfo(use = Id.NAME, property = "type", include = As.EXTERNAL_PROPERTY)
@JsonSubTypes(value = {
@JsonSubTypes.Type(value = Foo.class, name = "foo"),
@JsonSubTypes.Type(value = Bar.class, name = "bar")
})
private List<AbstractData> data;

// Getters and setters
}

public abstract class AbstractData {

private String someCommonProperty;

// Getters and setters
}

public class Foo extends AbstractData {

private String fooProperty;

// Getters and setters
}

public class Bar extends AbstractData {

private String barProperty;
private String type;
// Getters and setters
}

当我尝试如下反序列化时,在将 java 对象写为 json 时得到空字符串。

ObjectMapper mapper = new ObjectMapper();
Parent parent = mapper.readValue(json, Parent.class);

我收到这个错误:

 com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (START_OBJECT), expected START_ARRAY: need JSON Array to contain As.WRAPPER_ARRAY type information for class com.DemoJsonToJavaDeserialize.AbstractData
at [Source: C:<projectpath>\target\classes\foo.json; line: 3, column: 12] (through reference chain: com.DemoJsonToJavaDeserialize.Parent["data"]->java.util.ArrayList[0])

最佳答案

选项 1

如果您有权访问 AbstractData 类,您可能想要使用新的 2.12 Jackson Deduction 功能:

@JsonSubTypes(value = {
@JsonSubTypes.Type(value = Foo.class),
@JsonSubTypes.Type(value = Bar.class)
})
@JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION)
public abstract class AbstractData {
private String someCommonProperty;

// getters setters
}

然后,无需注释 FooBarParent:只要您的子类具有不同的属性名称,所有内容都会自动实例化. type json 属性也变得无用。

(如果你使用的是SpringBoot,你可以设置jackson-bom.version属性来升级spring boot中的jackson)

选项 2

JsonTypeInfo.As.EXTERNAL_PROPERTYjavadoc 说:另请注意,此机制不能用于容器值(数组、集合...。我相信这是你的问题:你正在将它应用于 List

如果您无法修改任何 Foo/Barr/AbstractData 类,经典方法是使用自定义反序列化器。在 Parent 类上:

    @JsonDeserialize(contentUsing = FooBarDeserializer.class)
private List<AbstractData> data;

反序列化器:

public class FooBarDeserializer extends JsonDeserializer<AbstractData> {
@Override
public AbstractData deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
JsonNode node = jsonParser.readValueAsTree();
if(node.has("fooProperty"))
return jsonParser.getCodec().treeToValue(node,Foo.class);
else
return jsonParser.getCodec().treeToValue(node,Bar.class);
}
}

如果您找到使用您的 Parent.type 的解决方案,请分享,我很感兴趣。

关于json - Jackson 多态反序列化和序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66555519/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com