2012-03-22 88 views
53

我有一個Java類MyPojo,我有興趣從JSON反序列化。我已經配置了一個特殊的MixIn類,MyPojoDeMixIn,以幫助我進行反序列化。 MyPojo只有intString實例變量與適當的getter和setters組合。 MyPojoDeMixIn看起來是這樣的:將JSON反序列化爲ArrayList <POJO>使用Jackson

public abstract class MyPojoDeMixIn { 
    MyPojoDeMixIn(
     @JsonProperty("JsonName1") int prop1, 
     @JsonProperty("JsonName2") int prop2, 
     @JsonProperty("JsonName3") String prop3) {} 
} 

在我的測試客戶端,我這樣做,當然,因爲有相關的類型不匹配JsonMappingException它不會在編譯時工作。

ObjectMapper m = new ObjectMapper(); 
m.getDeserializationConfig().addMixInAnnotations(MyPojo.class,MyPojoDeMixIn.class); 
try { ArrayList<MyPojo> arrayOfPojo = m.readValue(response, MyPojo.class); } 
catch (Exception e) { System.out.println(e) } 

我知道我可以通過創建一個只有在它的ArrayList<MyPojo>「響應」對象緩解這個問題,但我將不得不爲每一個類型我想回到創建這些有點無用之物。

我也在網上查看JacksonInFiveMinutes,但有一個可怕的時間瞭解有關Map<A,B>的東西,以及它如何與我的問題。如果你不能說,我完全不熟悉Java,並且來自Obj-C背景。他們特別提到:

除了結合POJO和「簡單」類型外,還有一個額外的 變種:即結合通用(類型)的容器。 由於所謂的類型擦除 (由Java用於實現向後兼容的 方式的泛型),這種情況需要特殊處理,這可以防止您使用類似 Collection.class(不能編譯)的東西。

所以,如果你想將數據綁定到一個地圖,你將需要使用:

Map<String,User> result = mapper.readValue(src, new TypeReference<Map<String,User>>() { }); 

我怎麼能直接反序列化ArrayList

回答

101

您可以使用TypeReference包裝器直接反序列化爲列表。的示例性方法:

public static <T> T fromJSON(final TypeReference<T> type, 
     final String jsonPacket) { 
    T data = null; 

    try { 
     data = new ObjectMapper().readValue(jsonPacket, type); 
    } catch (Exception e) { 
     // Handle the problem 
    } 
    return data; 
} 

並且因此使用:

final String json = ""; 
Set<POJO> properties = fromJSON(new TypeReference<Set<POJO>>() {}, json); 

TypeReference Javadoc

+0

你的回答似乎與他們的信息如何使用內置的'TypeReference'支持 - 我只是不明白怎麼辦呢?請參閱上面就如何指導我的編輯使用泛型。 – 2012-03-22 20:04:14

+0

嗯,它是相關的。但這是生產中代碼的一個片段。忘記你的mixin,只需使用我所展示的代碼(但是用當前實際bean類的名稱替換POJO)。 – Perception 2012-03-22 20:07:39

+0

您的代碼已編譯,但在嘗試打印出關於「NullPointerException」的'arrayList.toString()'時出現運行時異常。我猜測這可能是因爲我的POJO不符合其屬性的正確命名約定,也就是說,整個問題是Web服務返回Prop1Member而我的對象有Prop1。這是我使用mixins開始的唯一真正原因,所以我不必將'@ JsonProperty'的聲明放在我的純對象中。 – 2012-03-22 20:19:03

3

我也有同樣的問題。我有一個將被轉換爲ArrayList的json。

帳戶看起來像這樣。

Account{ 
    Person p ; 
    Related r ; 

} 

Person{ 
    String Name ; 
    Address a ; 
} 

以上所有類都已正確註釋。 我試過TypeReference>(){} ,但不起作用。

它給了我Arraylist,但ArrayList有一個linkedHashMap,其中包含一些更多的包含最終值的鏈接hashmaps。

我的代碼如下:

public T unmarshal(String responseXML,String c) 
{ 
    ObjectMapper mapper = new ObjectMapper(); 

    AnnotationIntrospector introspector = new JacksonAnnotationIntrospector(); 

    mapper.getDeserializationConfig().withAnnotationIntrospector(introspector); 

    mapper.getSerializationConfig().withAnnotationIntrospector(introspector); 
    try 
    { 
     this.targetclass = (T) mapper.readValue(responseXML, new TypeReference<ArrayList<T>>() {}); 
    } 
    catch (JsonParseException e) 
    { 
     e.printStackTrace(); 
    } 
    catch (JsonMappingException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    return this.targetclass; 
} 

我終於解決了這個問題。我可以列表直接轉換成JSON字符串到的ArrayList如下:

JsonMarshallerUnmarshaller<T>{ 

    T targetClass ; 

    public ArrayList<T> unmarshal(String jsonString) 
    { 
     ObjectMapper mapper = new ObjectMapper(); 

     AnnotationIntrospector introspector = new JacksonAnnotationIntrospector(); 

     mapper.getDeserializationConfig().withAnnotationIntrospector(introspector); 

     mapper.getSerializationConfig().withAnnotationIntrospector(introspector); 
     JavaType type = mapper.getTypeFactory(). 
        constructCollectionType(ArrayList.class, targetclass.getClass()) ; 
     try 
     { 
     Class c1 = this.targetclass.getClass() ; 
     Class c2 = this.targetclass1.getClass() ; 
      ArrayList<T> temp = (ArrayList<T>) mapper.readValue(jsonString, type); 
     return temp ; 
     } 
     catch (JsonParseException e) 
     { 
     e.printStackTrace(); 
     } 
     catch (JsonMappingException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

    return null ; 
    } 

} 
48

另一種方法是使用一個數組作爲一個類型,例如:

ObjectMapper objectMapper = new ObjectMapper(); 
MyPojo[] pojos = objectMapper.readValue(json, MyPojo[].class); 

這樣你避免所有的麻煩與類型的對象,如果你真的需要一個列表,你總是可以將數組轉換爲列表:

List<MyPojo> pojoList = Arrays.asList(pojos); 

恕我直言,這是更具可讀性。

,並使其成爲一個實際的列表(可以修改的,看到的Arrays.asList()限制),那麼只要做到以下幾點:

List<MyPojo> mcList = new ArrayList<>(Arrays.asList(pojos)); 
+2

這應該是被接受的答案,確實簡單並且可讀性更高。 – dic19 2017-01-12 20:18:54

+0

同意^這種方式更有幫助 – cstaikos 2017-07-06 15:18:09

7

這種變體看起來更加簡潔大方。

CollectionType typeReference = 
    TypeFactory.defaultInstance().constructCollectionType(List.class, Dto.class); 
List<Dto> resultDto = objectMapper.readValue(content, typeReference); 
相關問題