繁体   English   中英

如何使用杰克逊反序列化泛型类型?

[英]How to deserialize a generic type with jackson?

我尝试了许多解决方案,但我的情况似乎很特殊。 @JsonProperty必须取决于类类型:

我有两个实体的JSON:

“人”:[{“ id”:“ 452009517701”,“ name”:“ Perosn1”,“ address”:“ 541-DPL-355”}]

“汽车”:[{“ id”:5787544,“ brand”:“ Toyota”,“ number”:12454}]

实体看起来像:

public class Person{
    private String id:
    private String name;
    private String address:
    // Constcutors && Getters && Setters
}

public class Car{
    private Long id:
    private String brand;
    private Long number:
    // Constcutors && Getters && Setters
}

通用类:

public class GenericEntity<T>{
    //@JsonProperty
    private List<T> myList;
    // Constcutors && Getters && Setters
}

主类:

public static void main(String[] args) {
        ObjectMapper mapper=new ObjectMapper();
        GenericEntity p=mapper.readValue(personJson,GenericEntity.class);
        GenericEntity c=mapper.readValue(carJson,GenericEntity.class);
    }

调试时,我发现GenericEntity内的列表始终为空。 我不知道如何在GenericEntity内部列表的顶部动态设置jsonProperty。

另外,我用过:

Object readValue = mapper.readValue(jsonPerson, new TypeReference<GenericEntity<Person>>() {}); 

和:

JavaType javaType = mapper.getTypeFactory().constructParametricType(GenericEntity.class, Person.class);
        Object readValue =mapper.readValue(jsonPerson, javaType);

我知道了:

Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.test.GenericEntity` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('Person')
 at [Source: (String)""Person": [ { "id": "452009517701", "name": "Perosn1", "address": "541-DPL-355" } ]"; line: 1, column: 1]
    at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
    at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1343)
    at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1032)
    at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:371)
    at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:323)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1373)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:171)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:161)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)

最简单的选择是使用包装类型,每个集合类型都使用一个单独的字段,例如:

class GenericEntity {
    @JsonProperty("Car") List<Car> car; 
    @JsonProperty("Person") List<Person> person; 
}

这样,您总是可以填写其中一个列表(根据我们在评论中的对话)。 只要您没有太多的类型并且它不会经常更改就可以了:)

更高级的方法是使用自定义解串器,如下所示:

@JsonDeserialize(using = MyDeserializer.class)
class GenericEntity<T> {
    List<T> myList;

    GenericEntity(List<T> myList) {
        this.myList = myList;
    }
}

反序列化器本身必须自己创建一个GenericEntity ,但是它可以将所有特定类型反序列化的工作委派给其他反序列化器(因此,我们的工作就是告诉它要反序列化的类型和类型):

class MyDeserializer extends JsonDeserializer<GenericEntity<?>> {

    @Override
    public GenericEntity<?> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        ObjectCodec codec = p.getCodec();
        JsonNode node = codec.readTree(p);
        if (node.hasNonNull("Person")) {
            JsonParser nodeParser = node.get("Person").traverse(codec);
            nodeParser.nextToken();
            Person[] people = ctxt.readValue(nodeParser, Person[].class);
            return new GenericEntity<>(asList(people));
        } else if (node.hasNonNull("Car")) {
            JsonParser nodeParser = node.get("Car").traverse(codec);
            nodeParser.nextToken();
            Car[] cars = ctxt.readValue(nodeParser, Car[].class);
            return new GenericEntity<>(asList(cars));
        }
        throw new RuntimeException("Couldn't find a type to deserialize!");
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM