杰克逊JSON + Java泛型获取LinkedHashMap

33

我有一个问题,类似于Stackoverflow上的一些问题,但没有一个真正回答了我的问题。 我使用Jackson的ObjectMapper,想将这个JSON字符串解析成一个User对象列表:

[{ "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;
}

但我得到的是一个由LinkedHashMap组成的List

我的代码有什么问题?


3
这段内容是关于Java语言的类型擦除问题和Jackson JSON解析库的使用。其中T代表类型变量而非类型定义,因此需要传递Class参数来定义实际类型。通过这种方式,JSON对象可以绑定到正确的类并进行序列化和反序列化。 - StaxMan
1个回答

40
以下内容已经生效,根据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

2
正确。一个小注记是,为了避免弃用问题,您可以调用“objectMapper.getTypeFactory()”来使用非静态方法;在Jackson 1.8中进行此更改(使用TypeFactory实例)是必要的,以支持像Scala这样具有自己的Collection / Map类型的JVM语言... - StaxMan
1
@nsfyn55,你的回答包括了这种问题的两个主要点。使用T并使用非废弃的方法处理它。投票支持。 - kamaci
非常感谢,这个效果太棒了!即使是ChatGPT也无法提供这种解决方案! - Crossoni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接