Jackson 通过字段进行多态反序列化
Jackson Polymorphic Deserialization via field
比方说,我有一个 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
}
B的class类型根据A的typeId在变化,所以如果A的typeId是"XXX",数据字段的类型是BChildOne,如果A的typeId是"YYY", 数据字段类型为 BChildTwo.
我怎样才能做到这一点?
所以我试过了;
@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{
但是我遇到了以下错误;
Unexpected token (END_OBJECT), expected FIELD_NAME: missing property 'typeId' that is to contain type id (for class B)
这很明显,因为 typeId 字段在 class A 而不是 B。
我曾经遇到过同样的序列化问题,我做了一个这样的实现。请参阅下面的代码。
protected Entity serialize(Object entity) throws Exception {
try {
if ( entity instanceof AbstractProcessRequest ) {
AbstractProcessRequest request = (AbstractProcessRequest) entity;
String value = mapper.writeValueAsString(request.prepareJSONRequest());
logger.info("Telesales String json request " + value);
return new Entity(value, UTF_8);
} else {
String value = mapper.writeValueAsString(entity);
return new StringEntity(value, UTF_8);
}
} catch (Exception e) {
logger.error("Telesales --> Error occured serializing entity", e);
throw e;
}
}
为了实现通用结构,在某些服务中创建了一个执行方法 class,如下所示。
private <T> T execute(Object entity, Class<T> clazz, HttpRequestBase request, String contentType) throws Exception {
假设您的 JSON 文档如下:
{
"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确定对class映射data
属性。 JSON 文档可以反序列化如下:
ObjectMapper mapper = new ObjectMapper();
Wrapper wrapper = mapper.readValue(json, Wrapper.class);
比方说,我有一个 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
}
B的class类型根据A的typeId在变化,所以如果A的typeId是"XXX",数据字段的类型是BChildOne,如果A的typeId是"YYY", 数据字段类型为 BChildTwo.
我怎样才能做到这一点?
所以我试过了;
@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{
但是我遇到了以下错误;
Unexpected token (END_OBJECT), expected FIELD_NAME: missing property 'typeId' that is to contain type id (for class B)
这很明显,因为 typeId 字段在 class A 而不是 B。
我曾经遇到过同样的序列化问题,我做了一个这样的实现。请参阅下面的代码。
protected Entity serialize(Object entity) throws Exception {
try {
if ( entity instanceof AbstractProcessRequest ) {
AbstractProcessRequest request = (AbstractProcessRequest) entity;
String value = mapper.writeValueAsString(request.prepareJSONRequest());
logger.info("Telesales String json request " + value);
return new Entity(value, UTF_8);
} else {
String value = mapper.writeValueAsString(entity);
return new StringEntity(value, UTF_8);
}
} catch (Exception e) {
logger.error("Telesales --> Error occured serializing entity", e);
throw e;
}
}
为了实现通用结构,在某些服务中创建了一个执行方法 class,如下所示。
private <T> T execute(Object entity, Class<T> clazz, HttpRequestBase request, String contentType) throws Exception {
假设您的 JSON 文档如下:
{
"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确定对class映射data
属性。 JSON 文档可以反序列化如下:
ObjectMapper mapper = new ObjectMapper();
Wrapper wrapper = mapper.readValue(json, Wrapper.class);