如何获取Jackson的ObjectMapper的通用类型

问题描述 投票:3回答:3

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>
java jackson type-erasure
3个回答
5
投票

您是否尝试过映射器的constructType方法?

Type genericType = User.class.getField("listProp").getGenericType();
List<Long> correctList = om.readValue(jsonEntry.getValue(), om.constructType(genericType));

4
投票

杰克逊使用TypeReference构造通用类型

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

杰克逊使用JavaType构造通用类型

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

杰克逊支持三种类型

  1. 班级
  2. JavaType
  3. TypeReference

我喜欢使用JavaType,对于泛型类型更清楚,对于普通对象使用Class


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)而不是接口List


这对于给定的示例提出了一种更直接的方法-User已经是包装器(并且listProppublic):

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

然后

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

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

© www.soinside.com 2019 - 2024. All rights reserved.