You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中使用Jackson反序列化泛型抽象类的问题

问题出在这两点

当前content字段反序列化失败,核心问题有两个:

  1. @JsonTypeInfo配置错误:你给Content类设置的property="content",是让Jackson从子类的JSON结构内部读取类型标识字段,但你把它指定成了外层Template类的字段名,Jackson根本找不到识别依据。
  2. 泛型类型被擦除:运行时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的替代方案

如果不能调整请求体结构,可以用全类名作为类型标识(耦合性较高):

  1. 修改Content类的注解:
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "@class")
  1. 在请求JSON中添加全类名字段:
"content" : {
    "@class": "com.your.package.EmailContent",
    "subject" : "Test-Subject",
    "body" : "Test-body"
}
重点提醒
  • 不用@JsonDeserialize的前提下,必须给Jackson提供区分子类的标识字段,这是多态反序列化的必要条件。
  • 泛型类型必须在反序列化时明确指定,否则Jackson无法绕过类型擦除,无法确定具体的子类类型。

内容的提问来源于stack exchange,提问作者Sadaf Chowdhury

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 08:31:13