我有这个父类:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "objectType")
@JsonSubTypes(
{
@JsonSubTypes.Type(value = Child.class, name = "child"),
}
)
public class Parent {
@JsonProperty("objectType")
private ProductType productType
public ProductType getProductType { return productType; }
}
此类由子类扩展:
public class Child extends Parent {
@JsonProperty("field1")
private Field1 field1;
@JsonProperty("field2")
private Field2 field2;
}
我尝试解析以下表示Child
类序列化实例的 Json 文件:
{
"objectType" : "child1",
"field1" : "value1",
"field2" : "value2"
}
。使用以下代码:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enableDefaultTyping();
Parent parent = objectMapper.treeToValue(parentJsonNode, Parent.class);
(附言parentJsonNode
是通过读取 JSON 文件创建的JsonNode
(。
发生的情况是,我的对象的field1
和field2
被正确读取和设置,但是字段objectType
(声明到父类中(在解析后仍然null
。
我应该怎么做才能让杰克逊从 Json 对象中正确读取objectType
的值child
?
这是ProductType
的代码:
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum ProductType {
CHILD1("child1"), CHILD2("child2");
private String objectType;
private ProductType(String objectType) {
this.objectType = objectType;
}
@JsonValue
public String getObjectType() { return objectType; }
}
这是由于杰克逊的奇怪行为,即在编译时添加一个对您不明确可见的额外字段,以区分命名的子类,例如您在@JsonTypeInfo
中输入的值。因为您的父类包含序列化为名为objectType
的 JSON 属性的属性,并且@JsonTypeInfo
中给出的分母的名称也objectType
。如果要序列化Child
的对象,您会注意到序列化的对象包含两个同名的字段objectType
其中只有一个将被填充:
System.out.println(objectMapper.writeValueAsString(new Child()));
导致
{"objectType":"child","objectType":null,"field1":null,"field2":null}
解决方法是,如果在代码中不需要显式字段productType
(序列化为objectType
(,则跳过父类中的显式字段,或者为其指定不同的序列化名称(例如productType
(,但是您当然需要将第二个 JSON 字段反序列化到其中:
改变
public class Parent {
@JsonProperty("objectType")
private String productType;
自
public class Parent {
@JsonProperty("productType")
private String productType;
和
Parent parent = objectMapper.treeToValue(objectMapper.readTree("{n" +
" "objectType" : "child",n" +
" "productType" : "child",n" +
" "field1" : "value1",n" +
" "field2" : "value2"n" +
"}"), Parent.class);
System.out.println(parent.getProductType());
导致输出
child
第三种可能性是显式初始化字段,例如通过构造函数,因为 Jackson 使用默认构造函数在反序列化时创建对象:
// For subclasses
protected Parent (String productType) {
this.productType = productType;
}
// For Jackson
public Parent () {
}
和
public Child () {
super("child");
}
编辑:我使用String
而不是ProductType
来简化我的代码,但结果是相似的。