自定义 JSON 到 POJO 映射器
Custom JSON to POJO mapper
上下文
我正在尝试使用 RestTemplate GET 请求接收数据,服务器 returns 我需要的数据采用 JSON 格式,响应包含我需要的所有数据,但它还包含一个大量多余的数据,我不想将包含过多数据的过多字段添加到我的 POJO 以自动映射它。
问题是
我能否以某种方式制作自定义映射器,仅将某些 JSON 字段映射到我的 java class?非常感谢任何帮助
一些代码示例
之前我像这样将 JSON 直接映射到我的 POJO:
ResponseEntity<Foo> response = new RestTemplate(requestFactory)
.exchange(uri, HttpMethod.GET, entity, new ParameterizedTypeReference<Foo>(){});
但现在我使用的服务更改了它的 API 并以完全不同的格式发送数据。改变我的 java classes 真的很不愉快,所以我想知道我是否可以只映射需要的数据
我得到的 json 看起来像这样:
[{
"idReadable": "idR",
"customFields": [{
"projectCustomField": {
"field": {
"name": "Name",
"$type": "type"
},
"$type": "type"
},
"value": {
"name": "Value",
"$type": "type"
},
"$type": "type"
}],
"id": "id",
"$type": "type"
}]
我只需要两个“名称”值
解决方案
正如@mostneededrabbit 在评论中建议的那样,解决方案是为 RestTemplate 编写扩展 StdDeserializer 的自定义反序列化器,其中看起来像这样:
ArrayNode nodeList = jp.getCodec().readTree(jp);
HashMap<String, String> fields = new HashMap<>();
List<Issue> foos = new ArrayList<>();
for (JsonNode node : nodeList) {
String id = node.get("id").asText();
issues.add(new Foo(id));
}
要真正让它工作,您需要在发送请求之前执行以下操作:
var mapper = new ObjectMapper();
var module = new SimpleModule();
module.addDeserializer(Foo.class, new FooDeserializer());
mapper.registerModule(module);
var converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(mapper);
var restTemplate = new RestTemplate(requestFactory);
restTemplate.getMessageConverters().add(0, converter);
您可以忽略不需要的字段,方法是将其放在 class 的顶部:
@JsonIgnoreProperties(ignoreUnknown = true)
然后只保留 class.
中需要的字段
上下文
我正在尝试使用 RestTemplate GET 请求接收数据,服务器 returns 我需要的数据采用 JSON 格式,响应包含我需要的所有数据,但它还包含一个大量多余的数据,我不想将包含过多数据的过多字段添加到我的 POJO 以自动映射它。
问题是
我能否以某种方式制作自定义映射器,仅将某些 JSON 字段映射到我的 java class?非常感谢任何帮助
一些代码示例
之前我像这样将 JSON 直接映射到我的 POJO:
ResponseEntity<Foo> response = new RestTemplate(requestFactory)
.exchange(uri, HttpMethod.GET, entity, new ParameterizedTypeReference<Foo>(){});
但现在我使用的服务更改了它的 API 并以完全不同的格式发送数据。改变我的 java classes 真的很不愉快,所以我想知道我是否可以只映射需要的数据
我得到的 json 看起来像这样:
[{
"idReadable": "idR",
"customFields": [{
"projectCustomField": {
"field": {
"name": "Name",
"$type": "type"
},
"$type": "type"
},
"value": {
"name": "Value",
"$type": "type"
},
"$type": "type"
}],
"id": "id",
"$type": "type"
}]
我只需要两个“名称”值
解决方案
正如@mostneededrabbit 在评论中建议的那样,解决方案是为 RestTemplate 编写扩展 StdDeserializer 的自定义反序列化器,其中看起来像这样:
ArrayNode nodeList = jp.getCodec().readTree(jp);
HashMap<String, String> fields = new HashMap<>();
List<Issue> foos = new ArrayList<>();
for (JsonNode node : nodeList) {
String id = node.get("id").asText();
issues.add(new Foo(id));
}
要真正让它工作,您需要在发送请求之前执行以下操作:
var mapper = new ObjectMapper();
var module = new SimpleModule();
module.addDeserializer(Foo.class, new FooDeserializer());
mapper.registerModule(module);
var converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(mapper);
var restTemplate = new RestTemplate(requestFactory);
restTemplate.getMessageConverters().add(0, converter);
您可以忽略不需要的字段,方法是将其放在 class 的顶部:
@JsonIgnoreProperties(ignoreUnknown = true)
然后只保留 class.
中需要的字段