@jsontypeinfo通过在基类或接口上声明类型标识规则(如use=id.name、property="type")并配合@jsonsubtypes映射子类名称,使jackson能在反序列化时准确还原多态对象;include决定标识嵌入方式,visible=true可保留类型字段供业务使用。

Java中继承体系下JSON序列化多态类型丢失,本质是反序列化时Jackson不知道该还原成哪个子类。用 @JsonTypeInfo 注解就能明确告诉它——关键不是加不加,而是怎么加、加在哪、参数怎么配。
必须加在基类或接口上
不能只加在字段或方法上(除非你只想控制某个特定字段),真正起作用的是对抽象父类或接口的声明。比如:
- 定义一个
abstract class Animal或interface Pet - 在它上面标注
@JsonTypeInfo和@JsonSubTypes - 子类不需要额外注解(除非想覆盖默认行为)
选对 use 和 property 组合
最常用且推荐的是 use = JsonTypeInfo.Id.NAME,配合自定义名称和显式字段名:
-
@JsonTypeInfo(use = Id.NAME, property = "type")→ JSON里出现"type": "dog" - 搭配
@JsonSubTypes({@Type(value = Dog.class, name = "dog")}) - 避免用
Id.CLASS,否则JSON里会暴露完整类名(如"@class": "com.example.Dog"),耦合严重、不安全
注意 include 的实际效果
include 决定类型标识怎么嵌入JSON结构,90%场景用默认值即可:
-
include = As.PROPERTY(默认)→ 类型字段和业务字段平级,如{"type":"cat","name":"mimi"} -
include = As.EXISTING_PROPERTY→ 复用已有字段(比如POJO里本来就有String type),需确保该字段值与@JsonSubTypes.name一致 -
include = As.WRAPPER_OBJECT→ 整个对象被包一层,如{"cat":{"name":"mimi"}},适合API契约已固定的情况
别漏掉 visible = true 这个细节
默认 visible = false,意味着Jackson会在反序列化前悄悄删掉类型字段;如果业务逻辑后续还要读这个字段(比如前端展示类型),就得显式设为 true:
@JsonTypeInfo(use = Id.NAME, property = "type", visible = true)- 这样字段既参与类型判断,又保留在最终对象里
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











