Java通常会在编译时擦除Generics
数据,但是有可能获取该信息(Jackson ObjectMapper
表现得很好)。
我的问题:我有一个具有列表属性的类:
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>
您是否尝试过映射器的constructType方法?
Type genericType = User.class.getField("listProp").getGenericType();
List<Long> correctList = om.readValue(jsonEntry.getValue(), om.constructType(genericType));
杰克逊使用TypeReference构造通用类型
TypeReference typeReference =new TypeReference<List<Long>>(){}
杰克逊使用JavaType构造通用类型
JavaType jt = om.getTypeFactory().constructArrayType(Long.class);
杰克逊支持三种类型
我喜欢使用JavaType,对于泛型类型更清楚,对于普通对象使用Class
也许反通用化泛型类型的一种较不外在的方法是将其包装在具体类型内:
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
)而不是接口List
。
这对于给定的示例提出了一种更直接的方法-User
已经是包装器(并且listProp
为public
):
public class User {
public List<Long> listProp;
}
然后
String jsonStr = objMapper.writeValueAsString(user1); // serialize
var user2 = objMapper.readValue(jsonStr,User.class); // deserialize
在这种情况下,您可以按原样使用接口List
作为包装类中的字段类型,但这意味着您无法控制Jackson将使用的具体类型。