通过现场进行杰克逊多态反序列化 [英] Jackson Polymorphic Deserialization via field
问题描述
让我说一堂课
公共类A {私有UUID typeId;私人B资料;}公共抽象类B {私有字符串a;}公共课程BChildOne扩展了B {...一些变量}公共类BChildTwo扩展了B {...一些变量}
类B的类型正在更改,根据A的typeId,因此,如果A的typeId为"XXX",则数据字段的类型为BChildOne,而如果A的typeId为"YYY",则数据字段的类型为BChildTwo./p>
我该如何实现?
所以我尝试过;
<代码> @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY,getterVisibility =JsonAutoDetect.Visibility.NONE,setterVisibility =JsonAutoDetect.Visibility.NONE)@JsonIgnoreProperties(ignoreUnknown = true)@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,包括=JsonTypeInfo.As.EXTERNAL_PROPERTY,属性="typeId")@JsonSubTypes({@ JsonSubTypes.Type(值= BChildOne.class,名称="40ad2fe6-e672-4f0e-986e-619c7a1a3223)})公共抽象类B {
但是我遇到以下错误;
意外的令牌(END_OBJECT),预期的FIELD_NAME:缺少包含类型ID(用于B类)的属性"typeId"
这很明显,因为typeId字段在类A中而不在类B中.
假设您的JSON文档类似:
<代码> {"type":"foo",数据": {"someCommonProperty":公共财产","fooProperty":特定于foo的属性"}}
<代码> {"type":"bar",数据": {"someCommonProperty":公共财产","barProperty":栏特定属性"}}
您可以使用:
公共类包装器{私有字符串类型;@JsonTypeInfo(使用= Id.NAME,属性=类型",包含= As.EXTERNAL_PROPERTY)@JsonSubTypes(value = {@ JsonSubTypes.Type(值= Foo.class,名称="foo"),@ JsonSubTypes.Type(值= Bar.class,名称="bar")})私有AbstractData数据;//取得者和设定者}
公共抽象类AbstractData {私有字符串someCommonProperty;//取得者和设定者}
公共类Foo扩展了AbstractData {私有字符串fooProperty;//取得者和设定者}
公共类Bar扩展AbstractData {private String barProperty;//取得者和设定者}
采用这种方法, let's say, i have a class type of class B is changing, according to A's typeId , so if typeId of A is "XXX", type of data field is BChildOne, and if typeId of A is "YYY", type of data field is BChildTwo. how can i achive that? so for i tried that; but i got following error; Unexpected token (END_OBJECT), expected FIELD_NAME: missing property 'typeId' that is to contain type id (for class B) which is obvious, because typeId field is in class A not B. Assuming that your JSON documents are like:
You can use:
In this approach,
这篇关于通过现场进行杰克逊多态反序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! @JsonTypeInfo
设置为使用 type
作为 ObjectMapper mapper = new ObjectMapper();包装器包装器= mapper.readValue(json,Wrapper.class);
public class A{
private UUID typeId;
private B data;
}
public abstract class B{
private String a;
}
public class BChildOne extends B{
... some variables
}
public class BChildTwo extends B{
... some variables
}
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility =
JsonAutoDetect.Visibility.NONE, setterVisibility =
JsonAutoDetect.Visibility.NONE)
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include =
JsonTypeInfo.As.EXTERNAL_PROPERTY , property = "typeId")
@JsonSubTypes({
@JsonSubTypes.Type(value = BChildOne.class, name = "40ad2fe6-e672-4f0e-
986e-
619c7a1a3223") }
)
public abstract class B{
{
"type": "foo",
"data": {
"someCommonProperty": "common property",
"fooProperty": "foo specific property"
}
}
{
"type": "bar",
"data": {
"someCommonProperty": "common property",
"barProperty": "bar specific property"
}
}
public class Wrapper {
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 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;
// Getters and setters
}
@JsonTypeInfo
is set to use type
as an external property to determine the right class to map the data
property. The JSON document can be deserialized as following:ObjectMapper mapper = new ObjectMapper();
Wrapper wrapper = mapper.readValue(json, Wrapper.class);