Jackson反序列化对象列表为Map

3

我有自己的定制反序列化程序。

@Override
public Map<String, Car<?, ?>> deserialize(JsonParser p, DeserializationContext ctxt)
        throws IOException, JsonProcessingException {

    JsonNode carsNode = p.getCodec().readTree(p);
    Map<String, Car<?, ?>> CarsMap = new HashMap<String, Car<?, ?>>();
    ObjectMapper mapper = new ObjectMapper();

    for (JsonNode node : carsNode) {
        CarsMap.put(node.get("name").asText(), mapper.readValue(node.asText(), Car.class));
    }
    return CarsMap;
}

尽管 Car 是一个基类,而且地图应该有 Map String, Cars 的子类),但这并不起作用。

输入 JSON = [{"name": "本田", "type": "常规", "速度": 60}]

这应该在地图中,例如 Map.put("honda", RegularCar.class)


我只是想知道为什么你不将反序列化的结果转换成汽车列表,然后在另一个方法/类中将其转换为映射表呢? - Pulkownik
@Pulkownik 我实际上在反序列化汽车时遇到了麻烦 "mapper.readValue(node.asText(), Car.class)",这似乎不起作用。 - user3100209
你的汽车类是什么样子?你使用 @JsonDeserialize 吗? - Pulkownik
@Pulkownik,如果我使用实际类型进行反序列化,例如mapper.readValue(data, regularcar.class),那么这很简单。但是如果使用基类,则无法正常工作,即mapper.readValue(data, car.class)。 - user3100209
1
好的,你应该在这里阅读http://www.davismol.net/2015/03/05/jackson-json-deserialize-a-list-of-objects-of-subclasses-of-an-abstract-class/,了解如何处理jackson中的子类。 - Pulkownik
1个回答

2

您可以注释基本的Car类,告诉Jackson根据JSON中"type"字段的值实例化哪些子类。例如,如果您有RegularCarClassicCar扩展了Car

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, 
    property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = RegularCar.class, name = "Regular"),
    @JsonSubTypes.Type(value = ClassicCar.class, name = "Classic")
})
class Car {

这将使您可以像这样解析:
String json = "{\"name\": \"honda\", \"type\": \"Regular , \"speed\": 60}";
Car car = mapper.readValue(json, Car.class);

其中Car car实际上指向一个RegularCar实例。由于容器声明为Map<String, Car<, ?, >> CarsMap,所以这正是您要put进去的内容,然后适当地从Mapget并进行转换。


我希望在没有注解的情况下完成这个任务,因为那样我会与Jackson紧密耦合在一起。 - user3100209
@user3100209,您可以通过编程方式注册子类型的“Module”来替换@JsonSubTypes。您还可以使用“混合注释”将@JsonTypeInfo与基类相关联,而无需直接将其添加到该类中。 - StaxMan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接