我正在使用Spring RestTemplate和Jackson 2.1,我正在尝试反序列化下面的JSON字符串。而第一个数字是唯一的ID,因此这将是动态的:
{"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"}
我可以反序列化到UserDetails类,并按预期填充所有属性,因此我的配置应该是有序的。可能我需要在特定的地方注释UserDetailsWrapper类,或者我需要有一个自定义反序列化器。我试过这两个,但说实话,我不知道该怎么做。
如果有人可以帮助我,我会再次成为一个快乐的人。
答案 0 :(得分: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);
通过使用您提供的类型调用TypeFactory.constructType
来深入了解RestTemplate内部的代码,遗憾的是在途中丢失了您的泛型:
restTemplate.getForEntity("apiUrl", Map.class);
您not alone注意到缺乏通用支持,并且链接的答案指向您已经找到的内容:
restTemplate.exchange("apiUrl",
HttpMethod.GET,
null,
new ParameterizedTypeReference<Map<Long, UserDetails>>(){});
答案 1 :(得分: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 :: exchange()
答案 2 :(得分:0)
反映您的POJO结构的有效负载将是:
{"uniqueId":"2127388", "userDetails":{"name":"John","city":"Amsterdam","country":"The Netherlands"}}
我认为拥有可变的JSON属性名称(在您的情况下为2127388)并不是一个好主意。只需更改有效负载结构并按原样使用POJO。
评论反应:
我个人会重新考虑使用这样的API,因为它显然是非常糟糕的API。根据{{3}},属性的名称应该是字符串,而在这里它显然在语义上表示为数字。
如果您被迫使用它,只需使用Map<String, UserDetail>
作为您的包装。无论如何,它显然只有一个元素。