2016-01-06 113 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 ::交换()