反序列化动态字段名称的嵌套JSON对象
我使用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类,或者我需要一个自定义的反序列化器。我试了两次,但说实话,我不知道该怎么做。
如果有人能帮助我,我会再次成为一个快乐的人。
从类的名字,你真的不想要一个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>>(){});
有效载荷反映你的POJO的结构将是:
{"uniqueId":"2127388", "userDetails":{"name":"John","city":"Amsterdam","country":"The Netherlands"}}
我不认为这是具有可变的JSON属性名是个好主意(在你的案件2127388)。只需更改有效负载结构并按原样使用POJO。在评论
反应:
我会亲自重新使用这些API,因为这显然是非常糟糕的API。根据JSON spec,属性的名称应该是字符串,而这里显然是语义上的数字。
如果您被迫使用它,只需使用Map<String, UserDetail>
作为包装。无论如何,它显然只有一个元素。
太糟糕了,我不能改变有效载荷,它是由第三方提供派对API。 – Roan
我更新了我的回复 – luboskrnac
我已经基本解决它通过使用一个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 ::交换()
谢谢,这对我有所帮助。我发布了我的最终解决方案。 – Roan