Java中使用Jackson反序列化泛型抽象类的问题
问题出在这两点
当前content字段反序列化失败,核心问题有两个:
- @JsonTypeInfo配置错误:你给Content类设置的
property="content",是让Jackson从子类的JSON结构内部读取类型标识字段,但你把它指定成了外层Template类的字段名,Jackson根本找不到识别依据。 - 泛型类型被擦除:运行时Template
的泛型参数T会被抹除,Jackson默认无法知晓要把content反序列化为EmailContent子类。
解决办法
1. 修正Content类的类型识别配置
调整Content类上的注解,将类型标识字段设为子类JSON内部的字段(比如type),同时注册所有Content子类:
@Introspected @SuperBuilder @Getter @EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor(onConstructor_ = @JsonCreator) // 指定用子类内部的"type"字段识别类型,name对应子类的标识名 @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", visible = true) @JsonSubTypes({ @JsonSubTypes.Type(value = EmailContent.class, name = "EmailContent"), // 其他Content子类直接添加在此处,例如: // @JsonSubTypes.Type(value = SmsContent.class, name = "SmsContent") }) public abstract class Content { private String body; }
2. 给请求JSON添加类型标识
在content对象中加入type字段,值对应@JsonSubTypes中配置的子类标识名:
{ "name" : "jeff", "country" : "US", "content" : { "type": "EmailContent", "subject" : "Test-Subject", "body" : "Test-body" } }
3. 明确泛型类型(Controller层处理)
接收请求时直接指定泛型的具体类型,Spring会帮助Jackson绕过类型擦除问题:
@PostMapping("/your-api-endpoint") public ResponseEntity<?> processTemplate(@RequestBody Template<EmailContent> template) { // 业务逻辑处理 return ResponseEntity.ok(template); }
无法修改请求JSON的替代方案
如果不能调整请求体结构,可以用全类名作为类型标识(耦合性较高):
- 修改Content类的注解:
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "@class")
- 在请求JSON中添加全类名字段:
"content" : { "@class": "com.your.package.EmailContent", "subject" : "Test-Subject", "body" : "Test-body" }
重点提醒
- 不用
@JsonDeserialize的前提下,必须给Jackson提供区分子类的标识字段,这是多态反序列化的必要条件。 - 泛型类型必须在反序列化时明确指定,否则Jackson无法绕过类型擦除,无法确定具体的子类类型。
内容的提问来源于stack exchange,提问作者Sadaf Chowdhury
相关产品推荐
相关产品推荐

