4

Java 通常会在编译时擦除Generics数据,但有可能获得该信息(JacksonObjectMapper做得很好)。

我的问题:我有一个具有 List 属性的类:

public class User {
    public List<Long> listProp;//it is public only to keep the example simple
}

如何获得正确的TypeReference(或JavaType?),以便我可以以编程方式将 JSON 字符串映射到正确的列表类型,具有Class类的实例 (User.class) 和属性名称 (listProp)?我的意思是:

TypeReference typeReference = ...;//how to get the typeReference?
List<Long> correctList = om.readValue(jsonEntry.getValue(), typeReference);//this should return a List<Long> and not eg. a List<Integer>
4

3 回答 3

5

您是否尝试过 mappers 的constructType 方法?

Type genericType = User.class.getField("listProp").getGenericType();
List<Long> correctList = om.readValue(jsonEntry.getValue(), om.constructType(genericType));
于 2013-07-10T11:40:09.210 回答
4

jackson use TypeReference to construct generic type

TypeReference typeReference =new TypeReference<List<Long>>(){}

jackson use JavaType to construct generic type

JavaType jt = om.getTypeFactory().constructArrayType(Long.class);

jackson support three types

  1. Class
  2. JavaType
  3. TypeReference

i like use JavaType, it is more clear for generic type, for normal object use Class

于 2014-12-24T07:17:32.613 回答
0

反序列化泛型类型的一种不太奇特的方法可能是将其包装在具体类型中:

class ListLongWrapper extends ArrayList<Long> {} // package scope
... or ...
static class ListLongWrapper extends ArrayList<Long> {} // class scope

然后

String jsonStr = objMapper.writeValueAsString(user1.listProp); // serialize
user2.listProp = objMapper.readValue(jsonStr,ListLongWrapper.class); // deserialize

请注意,它extends需要一个类类型(这里我使用ArrayList)而不是 interface List


对于给定的示例,这表明了一种更直接的方法——User已经是一个包装器(并且listPropis public):

public class User {
    public List<Long> listProp;
}

然后

String jsonStr = objMapper.writeValueAsString(user1); // serialize
var user2 = objMapper.readValue(jsonStr,User.class); // deserialize

在这种情况下,您可以将接口List原样用作包装类中的字段类型,但这意味着您无法控制 Jackson 将使用的具体类型。

于 2020-04-13T20:43:12.010 回答