Spring Boot Jackson Databind:配置继承实现正确类型接收
解决Jackson反序列化基类到子类的类型识别问题
这个问题在Jackson处理多态类型反序列化时特别常见——默认情况下Jackson没办法自动判断该把JSON转换成哪个子类,所以会直接 fallback 到基类A。下面给你几种实用的解决方案:
方法一:给基类添加多态类型注解(最推荐)
直接在基类A上添加Jackson的@JsonTypeInfo和@JsonSubTypes注解,明确告诉Jackson如何识别不同的子类:
import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonSubTypes; @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type" // 用这个字段标识具体子类类型 ) @JsonSubTypes({ @JsonSubTypes.Type(value = B.class, name = "b"), @JsonSubTypes.Type(value = C.class, name = "c") }) public class A { public String a; }
配置完成后,客户端发送请求时需要在a的JSON对象里带上type字段,比如要传B类型的实例:
{ "a": { "type": "b", "a": "我是基类的字段", "b": "我是B类特有的字段" } }
Jackson会根据type字段的值自动把JSON反序列化成对应的B或C实例。
方法二:全局配置ObjectMapper(适合不想修改实体类的场景)
如果不想给实体类加注解,可以通过配置Spring的ObjectMapper来注册子类信息:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { ObjectMapper objectMapper = new ObjectMapper(); StdSubtypeResolver subtypeResolver = new StdSubtypeResolver(); // 注册所有需要识别的子类 subtypeResolver.registerSubtypes(B.class, C.class); objectMapper.setSubtypeResolver(subtypeResolver); // 也可以开启默认类型识别,序列化时自动添加@class字段标识类型 objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); return objectMapper; } }
这种方式下,客户端请求需要带上@class字段指定全类名,比如:
{ "a": { "@class": "com.yourpackage.B", "a": "基类字段", "b": "B类专属字段" } }
方法三:给Wrapper的字段指定反序列化器(单一子类场景)
如果Wrapper里的A总是固定某个子类,也可以直接在字段上强制指定反序列化目标类,不过这种方式灵活性很低,只适合特定场景:
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; public class Wrapper { @JsonDeserialize(as = B.class) // 强制把JSON反序列化成B类 public A a; }
额外提示
- Spring Boot环境下,默认的
ObjectMapper会自动识别@JsonTypeInfo这类注解,不需要额外配置 - 类型标识字段的名称可以自定义(比如改成
className),只要客户端和服务端保持一致即可 - 如果不想在JSON里暴露类型字段,也可以用
include = JsonTypeInfo.As.EXTERNAL_PROPERTY把类型字段放在Wrapper层级,和a字段关联
内容的提问来源于stack exchange,提问作者ivanjermakov
相关产品推荐
相关产品推荐

