2016-01-06 112 views
1

我使用Spring RestTemplate和Jackson 2.1,我試圖反序列化下面的JSON字符串。而第一個數字是一個唯一的ID,因此這將是動態的:反序列化動態字段名稱的嵌套JSON對象

{"2127388":{"name":"John","city":"Amsterdam","country":"The Netherlands"}} 

隨着RestTemplate我做了以下內容:

final ResponseEntity<UserDetailsWrapper> re = restTemplate.getForEntity(apiUrl, UserDetailsWrapper.class); 

的POJO的我是

class UserDetailsWrapper { 
    private long uniqueId; // [getter + setter] 
    private UserDetails userDetails; // [getter + setter] 

    // no args constructor + all properties constructor 
} 

class UserDetails { 
    private String name; // [getter + setter] 
    private String city; // [getter + setter] 
    private String country; // [getter + setter] 

    // no args constructor + all properties constructor 
} 

的UserDetailsWrapper類得到實例化,但其所有屬性保持爲空。

當我簡單地做:

{"name":"John","city":"Amsterdam","country":"The Netherlands"} 

我能夠deserialise與預期填充所有屬性的UserDetails類,所以我的配置應該是爲了。可能我需要在特定位置註釋UserDetailsWrapper類,或者我需要一個自定義的反序列化器。我試了兩次,但說實話,我不知道該怎麼做。

如果有人能幫助我,我會再次成爲一個快樂的人。

回答

2

從類的名字,你真的不想要一個Wrapper,你想有一個Map,像在這樣的回答:https://stackoverflow.com/a/18014407/785663

相反,他們使用那裏的String的,使用Long(未經測試):

TypeFactory typeFactory = mapper.getTypeFactory(); 
MapType mapType = typeFactory.constructMapType(HashMap.class, Long.class, UserDetails.class); 
HashMap<Long, UserDetails> map = mapper.readValue(json, mapType); 

挖掘到的代碼這正是RestTemplate致電TypeFactory.constructType與您提供的類型,可惜失去對你的方式仿製藥內部所做的:

restTemplate.getForEntity("apiUrl", Map.class); 

您在注意到缺乏泛型支持,以及相關的答案指向了你已經發現是not alone

restTemplate.exchange("apiUrl", 
     HttpMethod.GET, 
     null, 
     new ParameterizedTypeReference<Map<Long, UserDetails>>(){}); 
+0

謝謝,這對我有所幫助。我發佈了我的最終解決方案。 – Roan

0

有效載荷反映你的POJO的結構將是:

{"uniqueId":"2127388", "userDetails":{"name":"John","city":"Amsterdam","country":"The Netherlands"}} 

我不認爲這是具有可變的JSON屬性名是個好主意(在你的案件2127388)。只需更改有效負載結構並按原樣使用POJO。在評論

反應:

我會親自重新使用這些API,因爲這顯然是非常糟糕的API。根據JSON spec,屬性的名稱應該是字符串,而這裏顯然是語義上的數字。

如果您被迫使用它,只需使用Map<String, UserDetail>作爲包裝。無論如何,它顯然只有一個元素。

+0

太糟糕了,我不能改變有效載荷,它是由第三方提供派對API。 – Roan

+0

我更新了我的回覆 – luboskrnac

1

我已經基本解決它通過使用一個HashMap,然後拿到地圖的第一個條目。

final ParameterizedTypeReference<Map<Long, UserDetails>> ptr = 
      new ParameterizedTypeReference<Map<Long, UserDetails>>(){}; 

final ResponseEntity<Map<Long, UserDetails>> re = 
    restTemplate.exchange("apiUrl", HttpMethod.GET, null, ptr); 

因爲RestTemplate :: getForEntity()不支持添加類型引用,我不得不使用RestTemplate ::交換()