使用动态字段名

时间:2016-01-06 13:27:58

标签: java json spring jackson resttemplate

我正在使用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类,或者我需要有一个自定义反序列化器。我试过这两个,但说实话,我不知道该怎么做。

如果有人可以帮助我,我会再次成为一个快乐的人。

3 个答案:

答案 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>作为您的包装。无论如何,它显然只有一个元素。