resttemplate getForObject map responsetype

更新02/05/2018(大约4年后)…我再次对此进行了测试,因为人们一直在讨论我的问题/答案,Sotirios Delimanolis是正确的,我不应该在我的答案中编写代码来完成这项工作。 我使用了基本相同的RestTemplate / REST服务设置,如我的问题所示,REST服务具有已确认的响应内容类型application / json,RestTemplate能够处理响应而没有问题进入Map。


我正在调用一个返回JSON的rest服务,如下所示:

 { "some.key" : "some value", "another.key" : "another value" } 

我想我可以使用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 getBuildInfo(String buildUrl) { return restTemplate.getForObject(buildUrl, Map.class); } 

这是我如何设置restTemplate:

 @PostConstruct public void initialize() { List interceptors = new ArrayList(); interceptors.add(new ClientHttpRequestInterceptor() { @Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { HttpRequestWrapper requestWrapper = new HttpRequestWrapper(request); requestWrapper.getHeaders().setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); return execution.execute(requestWrapper, body); } }); restTemplate.setInterceptors(interceptors); } 

编辑二

完整的错误消息:

 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] at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:108) ~[spring-web-4.0.3.RELEASE.jar:4.0.3.RELEASE] at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:549) ~[spring-web-4.0.3.RELEASE.jar:4.0.3.RELEASE] at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:502) ~[spring-web-4.0.3.RELEASE.jar:4.0.3.RELEASE] at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:239) ~[spring-web-4.0.3.RELEASE.jar:4.0.3.RELEASE] at idexx.ordering.services.AwsServersServiceImpl.getBuildInfo(AwsServersServiceImpl.java:96) ~[classes/:na] 

正如我之前提到的,您的错误消息向我们显示您正在接收application/octet-stream作为Content-Type

 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的MappingJackson2HttpMessageConverter无法解析内容(它正在期待application/json )。


原始答案:

假设你的HTTP响应的Content-Typeapplication/json并且你在类路径上有Jackson 1或者2,那么RestTemplate可以像你一样将JSON反序列化为java.util.Map就好了。

你得到的错误,你没有完整显示,你要么注册了自定义的HttpMessageConverter对象,这些对象会覆盖默认值,或者你的类路径上没有Jackson,而且没有注册MappingJackson2HttpMessageConverter (这会做反序列化)或者你没有收到application/json

RestTemplate有一个名为exchange的方法,它将ParameterizedTypeReference的一个实例作为参数。

要创建一个返回java.util.Map的GET请求,只需创建一个inheritance自ParameterizedTypeReference的匿名类的实例。

 ParameterizedTypeReference> responseType = new ParameterizedTypeReference>() {}; 

然后,您可以调用exchange方法:

 RequestEntity request = RequestEntity.get(URI("http://example.com/foo")) .accept(MediaType.APPLICATION_JSON).build() Map jsonDictionary = restTemplate.exchange(request, responseType) 

更新02/05/2018(大约4年后)…我再次对此进行了测试,因为人们一直在讨论我的问题/答案,Sotirios Delimanolis是正确的,我不应该在我的答案中编写代码来完成这项工作。 我使用了基本相同的RestTemplate / REST服务设置,如我的问题所示,REST服务具有已确认的响应内容类型application / json,RestTemplate能够处理响应而没有问题进入Map。


我最终得到的内容为String ,然后将它们转换为这样的Map

 String json = restTemplate.getForObject(buildUrl, String.class); Map map = new HashMap(); ObjectMapper mapper = new ObjectMapper(); try { //convert JSON string to Map map = mapper.readValue(json, new TypeReference>(){}); } catch (Exception e) { logger.info("Exception converting {} to map", json, e); } return map; 

我认为你可以实现你的目标,只需使用RestTemplate并指定一个JsonNode作为响应类型。

  ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, entity, JsonNode.class); JsonNode map = response.getBody(); String someValue = map.get("someValue").asText(); 

我知道它的旧版本,但仅适用于可能访问此主题的其他人:如果您想使用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; }