Spring Boot Jackson使用JsonSubTypes时父类字段反序列化失败
解决Jackson多态反序列化时父类type字段为null的问题
我定义了如下Java类,使用Jackson实现多态反序列化:
public class TestClass { public ParentClass parentClass; public ParentClass getParentClass() { return parentClass; } public void setParentClass(ParentClass parentClass) { this.parentClass = parentClass; } @Override public String toString() { return "TestClass [parentClass=" + parentClass + "]"; } } @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") @JsonSubTypes({ @JsonSubTypes.Type(value = ChildClass1.class, name = "childClass1"), @JsonSubTypes.Type(value = ChildClass2.class, name = "childClass2") }) public class ParentClass { @JsonProperty public String type; public String getType() { return type; } public void setType(String type) { this.type = type; } @Override public String toString() { return "ParentClass [type=" + type + "]"; } } public class ChildClass1 extends ParentClass { public String childClass1Field; public String getChildClass1Field() { return childClass1Field; } public void setChildClass1Field(String childClass1Field) { this.childClass1Field = childClass1Field; } @Override public String toString() { return "ChildClass1 [childClass1Field=" + childClass1Field + ", type=" + type + "]"; } } public class ChildClass2 extends ParentClass { public String childClass2Field; public String getChildClass2Field() { return childClass2Field; } public void setChildClass2Field(String childClass2Field) { this.childClass2Field = childClass2Field; } @Override public String toString() { return "ChildClass2 [childClass2Field=" + childClass2Field + ", type=" + type + "]"; } }
当反序列化以下JSON负载时:
[{ "parentClass": { "type": "childClass1", "childClass1Field": "my child class 1 field value" } }]
得到的对象输出为:
[TestClass [parentClass=ChildClass1 [childClass1Field=my child class 1 field value, type=null]]]
多态实例化功能正常,已正确创建ChildClass1实例,但父类的type字段始终为null,而非预期的childClass1。
原因分析
Jackson的@JsonTypeInfo注解默认会消耗用于类型识别的字段(此处为type),仅用它来判断实例化哪个子类,不会再将该字段的值反序列化到类的对应属性中,这就是type字段为null的核心原因。
解决方法
方法1:配置visible = true保留类型字段
修改ParentClass上的@JsonTypeInfo注解,添加visible = true参数,让Jackson在完成类型识别后,仍将该字段的值反序列化到类属性中:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", visible = true) @JsonSubTypes({ @JsonSubTypes.Type(value = ChildClass1.class, name = "childClass1"), @JsonSubTypes.Type(value = ChildClass2.class, name = "childClass2") }) public class ParentClass { // 原有代码无需修改 }
方法2:分离类型识别字段与类属性名
如果不想修改@JsonTypeInfo的默认行为,可以将类中的属性名与JSON里的类型识别字段名区分开,比如把类中的type改为typeName,通过@JsonProperty映射JSON中的type字段:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") @JsonSubTypes({ @JsonSubTypes.Type(value = ChildClass1.class, name = "childClass1"), @JsonSubTypes.Type(value = ChildClass2.class, name = "childClass2") }) public class ParentClass { @JsonProperty("type") public String typeName; public String getTypeName() { return typeName; } public void setTypeName(String typeName) { this.typeName = typeName; } @Override public String toString() { return "ParentClass [type=" + typeName + "]"; } }
同时需要修改子类的toString方法,将引用的type替换为typeName。
内容的提问来源于stack exchange,提问作者ustad
相关产品推荐
相关产品推荐

