Jackson JSON + Java 泛型获取 LinkedHashMap

Posted

技术标签:

【中文标题】Jackson JSON + Java 泛型获取 LinkedHashMap【英文标题】:Jackson JSON + Java Generics get LinkedHashMap 【发布时间】:2011-08-12 12:45:37 【问题描述】:

我有一个问题类似于 *** 上的一些问题,但没有一个真正回答我的问题。我使用 Jackson 的 ObjectMapper 并希望将此 JSON 字符串解析为用户对象列表:

[ "user" : "Tom", "role" : "READER" , 
  "user" : "Agnes", "role" : "MEMBER" ]

我这样定义一个内部类:

public class UserRole 

    private String user
    private String role;

    public void setUser(String user) 
        this.user = user;
    

    public void setRole(String role) 
        this.role = role;
    

    public String getUser() 
        return user;
    

    public String getRole() 
        return role;
    

要将 JSON 字符串解析为 UserRoles 列表,我使用泛型:

protected <T> List<T> mapJsonToObjectList(String json) throws Exception 
    List<T> list;
    try 
        list = mapper.readValue(json, new TypeReference<List<T>>() );
     catch (Exception e) 
        throw new Exception("was not able to parse json");
    
    return list;

但我得到的是ListLinkedHashMaps

我的代码有什么问题?

【问题讨论】:

它是 Java 语言,臭名昭著的类型擦除: T 里面有一个类型变量而不是类型定义;并且基本上意味着您要求 List。 Jackson 然后使用“自然”对象类型绑定 JSON,然后 JSON 对象变成一个 Map(类型为 LinkedHashMap,保留顺序)。您通过传递 Class 正确地解决了问题,然后它确实定义了实际类型。 【参考方案1】:

以下有效,根据 StaxMan 的建议,不再使用已弃用的静态 collectionType() 方法。

public class SoApp


   /**
    * @param args
    * @throws Exception
    */
   public static void main(String[] args) throws Exception
   
      System.out.println("Hello World!");

      String s = "[\"user\":\"TestCity\",\"role\":\"TestCountry\",\"user\":\"TestCity\",\"role\":\"TestCountry\"]";
      StringReader sr = new StringReader("\"user\":\"TestCity\",\"role\":\"TestCountry\"");
      //UserRole user = mapper.readValue(sr, UserRole.class);

      mapJsonToObjectList(s,UserRole.class);

   

   protected static <T> List<T> mapJsonToObjectList(String json, Class<T> clazz) throws Exception
   
      List<T> list;
      ObjectMapper mapper = new ObjectMapper();
      System.out.println(json);
      TypeFactory t = TypeFactory.defaultInstance();
      list = mapper.readValue(json, t.constructCollectionType(ArrayList.class,clazz));

      System.out.println(list);
      System.out.println(list.get(0).getClass());
      return list;
   

...

public class UserRole

   private String user;
   private String role;

   public void setUser(String user) 
       this.user = user;
   

   public void setRole(String role) 
       this.role = role;
   

   public String getUser() 
       return user;
   

   public String getRole() 
       return role;
   

   @Override
   public String toString()
   
      return "UserRole [user=" + user + ", role=" + role + "]";
   
   

输出...

 Hello World!
["user":"TestCity","role":"TestCountry","user":"TestCity","role":"TestCountry"]
[UserRole [user=TestCity, role=TestCountry], UserRole [user=TestCity, role=TestCountry]]
class com.test.so.fix.UserRole

【讨论】:

正确。一个小提示是,为了解决弃用问题,您可以调用“objectMapper.getTypeFactory()”来使用非静态方法; Jackson 1.8 中的这种更改(使用 TypeFactory 实例)对于支持 Scala 等具有自己的 Collection/Map 类型的 JVM 语言是必要的...... @nsfyn55 您的回答包括此类问题的两个要点。使用 T 并使用非弃用方法处理它。投票。

以上是关于Jackson JSON + Java 泛型获取 LinkedHashMap的主要内容,如果未能解决你的问题,请参考以下文章

Jackson将json字符串转换成泛型List

Jackson序列化(8)— 支持泛型的反序列化

Jackson 将数组json转List泛型

Jackson反序列化泛型List(使用JavaType将json字符串转换成泛型List)

Jackson将json字符串转换成泛型List

json之jackson的常用全局配置以及自定义序列化规则