0

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

我有两个实体的 JSON:

“人”:[{“id”:“452009517701”,“名称”:“Perosn1”,“地址”:“541-DPL-355”}]

“汽车”:[{“id”:5787544,“品牌”:“丰田”,“号码”: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 中的列表始终为空。我不知道如何在 .json 列表的顶部动态设置 jsonProperty GenericEntity

另外,我用过:

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)
4

1 回答 1

2

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

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!");
    }
}
于 2019-04-15T15:39:58.830 回答