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

如何让ObjectMapper根据JSON的type字段创建对应子类实例?

Jackson ObjectMapper 根据type字段反序列化子类实例

问题场景

现有如下Java类结构:

public class SomeClass {
    ArrayList<BaseClass> list;
}
public class BaseClass {
    String id;
    String type;
}
public class MyClass1 extends BaseClass{
}
public class MyClass2 extends BaseClass{
}

对应的JSON数据:

{
    "list": [
      {
        "id": "1",
        "type": "MyClass1"
      },
      {
        "id": "2",
        "type": "MyClass2"
      },
      {
        "id": "3",
        "type": "MyClass1"
      }
    ]
}

需要让ObjectMapper根据type字段的值,将列表中的对象反序列化为对应的子类(MyClass1/MyClass2)而非父类BaseClass实例。


解决方案:使用Jackson类型注解

这是最直接的实现方式,通过在父类BaseClass上添加Jackson的类型识别注解,指定用type字段判断要实例化的子类:

修改BaseClass类,添加@JsonTypeInfo和@JsonSubTypes注解:

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.EXISTING_PROPERTY,
    property = "type", // 指定用来判断类型的字段
    visible = true // 保留type字段的值,不会被Jackson自动处理
)
@JsonSubTypes({
    @JsonSubTypes.Type(value = MyClass1.class, name = "MyClass1"),
    @JsonSubTypes.Type(value = MyClass2.class, name = "MyClass2")
})
public class BaseClass {
    String id;
    String type;
    
    // 需添加getter/setter,Jackson依赖它们访问字段
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }
    public String getType() { return type; }
    public void setType(String type) { this.type = type; }
}

验证反序列化

之后正常使用ObjectMapper反序列化即可,Jackson会自动根据type字段创建对应子类实例:

import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        String json = "{\"list\":[{\"id\":\"1\",\"type\":\"MyClass1\"},{\"id\":\"2\",\"type\":\"MyClass2\"},{\"id\":\"3\",\"type\":\"MyClass1\"}]}";
        ObjectMapper mapper = new ObjectMapper();
        SomeClass someClass = mapper.readValue(json, SomeClass.class);
        
        // 验证每个元素的类型
        for (BaseClass item : someClass.list) {
            System.out.println(item.getClass().getSimpleName());
        }
        // 输出:MyClass1、MyClass2、MyClass1
    }
}

注意事项

  • 必须确保BaseClass、MyClass1、MyClass2有公共无参构造方法,Jackson默认依赖它实例化对象。
  • 如果type字段值和子类名称不一致,可在@JsonSubTypes.Type的name属性指定对应关系,比如name = "TYPE1"对应MyClass1.class。
  • 若不想用注解,也可自定义TypeResolverBuilder或DeserializationProblemHandler实现类型判断,但注解方式最简洁。

内容的提问来源于stack exchange,提问作者Bitlejuce Do

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 13:28:36