2011-08-12 97 views
24

我有一個類似於在stackoverflow的一些問題,但沒有真正回答我的問題的問題。我用傑克遜的ObjectMapper並希望這個JSON字符串解析爲用戶對象的列表:Jackson JSON + Java泛型得到LinkedHashMap

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

但我得到的回覆是的LinkedHashMaps一個List

我的代碼有什麼問題?

+1

這是Java語言,和臭名昭著的類型擦除:T IN有一個類型的變量,而不是類型定義;基本上意味着你要求名單。然後Jackson使用'自然'對象類型綁定JSON,然後JSON對象變成一個Map(保留排序的LinkedHashMap類型)。您通過傳遞Class來正確地解決問題,Class然後定義實際類型。 – StaxMan

回答

30

以下工作和按照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(new UserRole(),s,UserRole.class); 

    } 

    protected static <T> List<T> mapJsonToObjectList(T typeDef,String json,Class 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

+0

@StaxMan - 謝謝更新以包含未棄用的方法 – nsfyn55

+1

@ nsfyn55您的答案包括兩個主要這類問題的要點。使用'T'並使用非棄用的方法處理它。投票。 – kamaci