Java resttemplate getForObject映射响应类型
2018年5月2日更新(大约4年后)…我再次测试了这一点,因为人们对我的问题/答案进行了投票,Sotirios Delimanolis认为我不必在我的答案中编写代码来实现这一点是正确的。我使用了与我的问题中所示基本相同的RestTemplate/REST服务设置,REST服务的确认响应内容类型为application/json,并且RestTemplate能够在地图中处理响应,没有任何问题。Java resttemplate getForObject映射响应类型,java,json,spring,resttemplate,Java,Json,Spring,Resttemplate,2018年5月2日更新(大约4年后)…我再次测试了这一点,因为人们对我的问题/答案进行了投票,Sotirios Delimanolis认为我不必在我的答案中编写代码来实现这一点是正确的。我使用了与我的问题中所示基本相同的RestTemplate/REST服务设置,REST服务的确认响应内容类型为application/json,并且RestTemplate能够在地图中处理响应,没有任何问题。 我正在调用一个返回JSON的rest服务,如下所示: { "some.key" : "some
我正在调用一个返回
JSON
的rest服务,如下所示:
{
"some.key" : "some value",
"another.key" : "another value"
}
String json = restTemplate.getForObject(buildUrl, String.class);
Map<String,String> map = new HashMap<String,String>();
ObjectMapper mapper = new ObjectMapper();
try {
//convert JSON string to Map
map = mapper.readValue(json, new TypeReference<HashMap<String,String>>(){});
} catch (Exception e) {
logger.info("Exception converting {} to map", json, e);
}
return map;
我想我可以用java.util.Map
作为响应类型来调用这个服务,但这对我不起作用。我得到一个例外:
org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [interface java.util.Map]
我是否应该指定String
作为响应类型,并将JSON
转换为Map
编辑一
这是我的restTemplate调用:
private Map<String, String> getBuildInfo(String buildUrl) {
return restTemplate.getForObject(buildUrl, Map.class);
}
正如我之前提到的,您的错误消息向我们显示,您正在以
内容类型
的形式接收应用程序/octet流
org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [interface java.util.Map] and content type [application/octet-stream]
因此,Jackson的映射Jackson2HttpMessageConverter
无法解析内容(它需要应用程序/json
)
原始答复: 假设HTTP响应的
内容类型
是application/json
,并且类路径上有Jackson 1或Jackson 2,那么RestTemplate
可以像反序列化到java.util.Map
中一样反序列化json
对于您得到的错误,您没有完整显示,或者您注册了覆盖默认值的自定义HttpMessageConverter
对象,或者您的类路径上没有Jackson,并且没有注册MappingJackson2HttpMessageConverter
(这将进行反序列化)或者您没有收到2018年5月2日更新的应用程序/json(大约4年后)…我再次测试了这一点,因为人们一直在对我的问题/答案进行投票,Sotirios Delimanolis是正确的,我不应该在我的答案中编写代码来实现这一点。我使用了与我的问题中所示基本相同的RestTemplate/REST服务设置,REST服务的确认响应内容类型为application/json,并且RestTemplate能够在地图中处理响应,没有任何问题。
我最终将内容作为字符串
获取,然后将其转换为映射
,如下所示:
{
"some.key" : "some value",
"another.key" : "another value"
}
String json = restTemplate.getForObject(buildUrl, String.class);
Map<String,String> map = new HashMap<String,String>();
ObjectMapper mapper = new ObjectMapper();
try {
//convert JSON string to Map
map = mapper.readValue(json, new TypeReference<HashMap<String,String>>(){});
} catch (Exception e) {
logger.info("Exception converting {} to map", json, e);
}
return map;
String json=restemplate.getForObject(buildUrl,String.class);
Map Map=newhashmap();
ObjectMapper mapper=新的ObjectMapper();
试一试{
//将JSON字符串转换为映射
map=mapper.readValue(json,newTypeReference(){});
}捕获(例外e){
info(“将{}转换为映射的异常”,json,e);
}
返回图;
我知道它很古老,但只针对可能访问此主题的其他人:
如果您想用RestTemplateBuilder注册一些额外的转换器,您还必须显式注册默认转换器
@Bean
public RestTemplateBuilder builder() {
return new RestTemplateBuilder()
.defaultMessageConverters()
.additionalMessageConverters(halMessageConverter());
}
private HttpMessageConverter halMessageConverter() {
ObjectMapper objectMapper = new ObjectMapper().registerModule(new Jackson2HalModule());
TypeConstrainedMappingJackson2HttpMessageConverter halConverter = new TypeConstrainedMappingJackson2HttpMessageConverter(ResourceSupport.class);
halConverter.setSupportedMediaTypes(Collections.singletonList(MediaTypes.HAL_JSON));
halConverter.setObjectMapper(objectMapper);
return halConverter;
}
restemplate有一个名为的方法,该方法将的实例作为参数
要发出返回java.util.Map
的GET请求,只需创建从ParameterizedTypeReference继承的匿名类的实例
ParameterizedTypeReference<HashMap<String, String>> responseType =
new ParameterizedTypeReference<HashMap<String, String>>() {};
ParameteredTypeReference响应类型=
新的ParameteredTypeReference(){};
然后可以调用exchange方法:
RequestEntity<Void> request = RequestEntity.get(URI("http://example.com/foo"))
.accept(MediaType.APPLICATION_JSON).build()
Map<String, String> jsonDictionary = restTemplate.exchange(request, responseType)
RequestEntity request=RequestEntity.get(URI(“http://example.com/foo"))
.accept(MediaType.APPLICATION_JSON).build()
Map jsonDictionary=restTemplate.exchange(请求,响应类型)
我认为,只要使用RestTemplate并将JsonNode指定为响应类型,就可以实现您的目标
ResponseEntity<JsonNode> response =
restTemplate.exchange(url, HttpMethod.GET, entity, JsonNode.class);
JsonNode map = response.getBody();
String someValue = map.get("someValue").asText();
ResponseEntity响应=
exchange(url,HttpMethod.GET,entity,JsonNode.class);
JsonNode map=response.getBody();
字符串someValue=map.get(“someValue”).asText();
@GetMapping(value=“getSunny/{userId}”)
公共地图getSunny(@PathVariable int sunnyId){
Map newObj=newhashmap();
最终字符串url=”http://localhost:8085/Sunny/getSunny/{sunnyId}”;
RestTemplate RestTemplate=新RestTemplate();
newObj=restemplate.getForObject(url,Map.class,sunnyId);
返回newObj;
}
它对我有效…在密钥名称中有点有效吗?我想这会有点让人困惑。@EngineerDollery它是JSON,很好。你能告诉我们如何创建和使用你的RestTemplate
?@SotiriosDelimanolis——它是JSON,所以是有效的,但仍然不好。如果您想将其转换为javascript对象,然后使用点表示法访问该对象,您将有点为难。@EngineerDollery我很确定javascript足够聪明来处理这个问题。在任何情况下,错误消息都与键的值无关。这是多余和不必要的。您正在创建和使用一个ObjectMapper
,这与RestTemplate
应该做的几乎一模一样。这不应该是公认的答案,您不需要编写代码就可以做到这一点@道格:我接受了自己的答案,因为它对我有用。我发现很多时候我只需要完成工作,继续前进。我还没有测试Sotirios Delimanolis的答案,但我怀疑他是正确的。@ZackMacomber请发布完整的stacktrace和完整的错误消息。oops-忘记发布了…现在就把它放在那里了。@ZackMacomber从错误消息中可以看出,响应的内容类型
没有设置为application/json
。这就是你需要改变的。如果你的API没有返回它,就像你对请求所做的那样注入它。只是澄清一下,这意味着你可以这样做:ResponseEntityAllo,还有一件事要检查,因为我就要输了
@GetMapping(value = "getSunny/{userId}")
public Map<String, SunnyVO> getSunny(@PathVariable int sunnyId) {
Map<String, SunnyVO> newObj = new HashMap<String, SunnyVO>();
final String url = "http://localhost:8085/Sunny/getSunny/{sunnyId}";
RestTemplate restTemplate = new RestTemplate();
newObj = restTemplate.getForObject(url, Map.class, sunnyId);
return newObj;
}