跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

Spring Boot Jackson 多态反序列化时父类字段为空的解决方案

本文解决 spring boot 中使用 jackson 的 @jsonsubtypes 进行多态反序列化时,父类中用于类型标识的字段(如 type)值为 null 的问题,核心在于正确配置 @jsontypeinfo 的 include 和 visible 属性。 本文解决 spring boot 中使用 jackson 的 @jsonsubtypes 进行多态反序列化时,父类中用于类型标识的字段(如 type)值为 null 的问题,核心在于正确配置 @jsontypeinfo 的 include 和 visible 属性。 在 Spring Boot 应用中,当使用 Jackson 实现基于类型的多态反序列化(如通过 @JsonTypeInfo + @JsonSubTypes),一个常见陷阱是:子类实例能被正确创建,但父类中声明的类型标识字段(例如 type)却始终为 null。这并非 Jackson 无法识别类型,而是默认行为未将类型信息写入目标字段。 根本原因在于:Jackson 默认将类型信息作为 额外元数据 注入(如添加 "type": "childClass1" 到 JSON 外层),而非赋值给 Java 字段。即使你在父类中定义了 type 字段并标注 @JsonProperty,若未显式告知 Jackson “该字段既用于类型识别,也需参与反序列化”,它就不会将解析出的类型名写入该字段。 ✅ 正确解法是修改 @JsonTypeInfo 注解,启用 EXISTING_PROPERTY 模式并设 visible = true:
@JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, // 关键:复用已存在字段,而非新增 property = "type", visible = true // 关键:使 type 字段对反序列化器可见(即允许写入) ) @JsonSubTypes({ @JsonSubTypes.Type(value = ChildClass1.class, name = "childClass1"), @JsonSubTypes.Type(value = ChildClass2.class, name = "childClass2") }) public class ParentClass { protected String type; // 注意:建议使用 protected 或 package-private,避免 public 引发意外覆盖 public String getType() { return type; } public void setType(String type) { this.type = type; } }
⚠️ 注意事项: include = As.EXISTING_PROPERTY 表示 Jackson 将从 JSON 中读取 "type" 字段的值,并赋给 ParentClass.type,同时依据该值决定实例化哪个子类; visible = true 是必需的——它告诉 Jackson:该 type 字段不仅是类型标识符,也是普通业务字段,需参与反序列化流程(否则即使字段存在,也不会被赋值); 父类中的 type 字段 不应 再额外加 @JsonProperty("type")(可能引发重复绑定),Jackson 会自动处理; 子类中无需重写 type 字段或 setter/getter,继承即可; 若使用 Lombok,建议对 ParentClass 使用 @Getter @Setter 而非 @Data(避免 @Data 自动生成的 equals/hashCode 意外包含 type 导致逻辑异常)。 完整验证示例(Spring Boot 环境下):
// 测试反序列化 String json = """ { "parentClass": { "type": "childClass1", "childClass1Field": "my child class 1 field value" } } """; TestClass testObj = new ObjectMapper().readValue(json, TestClass.class); System.out.println(testObj); // 输出:TestClass [parentClass=ChildClass1 [childClass1Field=my child class 1 field value, type=childClass1]]
? 总结:Jackson 多态反序列化的字段空值问题,本质是类型信息与业务字段的绑定配置缺失。只需两处关键调整——include = EXISTING_PROPERTY 和 visible = true——即可让 type 字段既驱动多态,又承载业务值,实现语义与功能的统一。

相关文章