【问题标题】:How to get the Generic type for the Jackson ObjectMapper如何获取 Jackson ObjectMapper 的通用类型
【发布时间】:2013-07-10 10:39:19
【问题描述】:

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

我的问题:我有一个具有 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>

【问题讨论】:

    标签: java jackson type-erasure


    【解决方案1】:

    你试过mappers的constructType方法吗?

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

    【讨论】:

      【解决方案2】:

      jackson 使用 TypeReference 构造泛型类型

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

      jackson 使用 JavaType 构造泛型类型

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

      jackson 支持三种类型

      1. Java 类型
      2. 类型参考

      我喜欢用JavaType,泛型比较清楚,普通对象用Class

      【讨论】:

      • 这正是我想要的。谢谢!
      【解决方案3】:

      也许反序列化泛型类型的一种不那么奇特的方法是将其包装在具体类型中:

      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 将使用的具体类型。

      【讨论】:

      • 令人惊讶的是嵌套泛型类型正常工作。只有当顶层是泛型时,您才需要跳过箍来定义 Jackson 的类型。
      猜你喜欢
      • 2015-07-07
      • 2015-07-15
      • 1970-01-01
      • 1970-01-01
      • 2016-11-03
      • 1970-01-01
      • 1970-01-01
      • 2014-05-06
      • 2015-05-18
      相关资源
      最近更新 更多