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

如何用Jackson处理含父类与子类的JSON数组生成List<Car>?

解决方案:Jackson多态反序列化实现混合类型List

要解决这个问题,核心是让Jackson在反序列化时能识别JSON对应的具体子类类型,下面是两种可行的实现方案:

方案一:通过类型注解配置(推荐)

这种方式需要在父类上添加多态注解,同时让Web服务返回的JSON包含类型标记字段,是最规范可靠的做法。

1. 给父类Car添加多态注解

在Car类上添加@JsonTypeInfo和@JsonSubTypes,明确类型识别规则和子类映射:

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

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "type" // 指定JSON中用来标记类型的字段名
)
@JsonSubTypes({
    @JsonSubTypes.Type(value = Car.class, name = "car"),
    @JsonSubTypes.Type(value = Truck.class, name = "truck")
})
public class Car {
    private String brand;
    private String model;

    // 构造方法、getter/setter省略
}

2. 确保JSON包含类型标记

Web服务返回的JSON数组中,每个对象需要携带type字段,用来区分是Car还是Truck:

[
    {
        "type": "car",
        "brand": "Toyota",
        "model": "Camry"
    },
    {
        "type": "truck",
        "brand": "Ford",
        "model": "F-150",
        "maxLoad": 5000,
        "clearance": 12
    }
]

3. 正常反序列化

直接用ObjectMapper反序列化为List<Car>即可,Jackson会自动识别类型并生成对应实例:

import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;

public class TestDeserialization {
    public static void main(String[] args) throws Exception {
        String jsonStr = "[...]"; // 替换为实际JSON字符串
        ObjectMapper mapper = new ObjectMapper();
        List<Car> carList = mapper.readValue(
            jsonStr,
            mapper.getTypeFactory().constructCollectionType(List.class, Car.class)
        );

        // 验证结果
        for (Car item : carList) {
            if (item instanceof Truck) {
                Truck truck = (Truck) item;
                System.out.println("卡车最大载重:" + truck.getMaxLoad());
            } else {
                System.out.println("轿车型号:" + item.getModel());
            }
        }
    }
}

方案二:自定义反序列化器(无类型标记时使用)

如果无法修改Web服务返回的JSON格式,没有type字段,可以通过自定义反序列化器,根据子类特有的属性判断类型。

1. 编写自定义反序列化器

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;

import java.io.IOException;

public class CarDeserializer extends StdDeserializer<Car> {

    protected CarDeserializer() {
        super(Car.class);
    }

    @Override
    public Car deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
        JsonNode node = jp.getCodec().readTree(jp);
        // 根据Truck特有的属性判断类型
        if (node.has("maxLoad") && node.has("clearance")) {
            return jp.getCodec().treeToValue(node, Truck.class);
        } else {
            return jp.getCodec().treeToValue(node, Car.class);
        }
    }
}

2. 注册反序列化器

在父类Car上添加注解,指定使用自定义反序列化器:

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

@JsonDeserialize(using = CarDeserializer.class)
public class Car {
    // 原有属性和方法省略
}

之后同样可以正常反序列化为List<Car>,Jackson会自动根据属性存在性判断实例类型。


内容的提问来源于stack exchange,提问作者Gary Greenberg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 10:30:54