更新02/05/2018(大约4年后)...我再次对此进行了测试,因为人们一直在回答我的问题/答案,Sotirios Delimanolis是正确的,我不应该写我的答案中的代码使这项工作。我使用了基本相同的RestTemplate / REST服务设置,如我的问题所示,REST服务具有确认的响应内容类型application / json,RestTemplate能够处理响应而没有问题进入Map。
我正在调用一个返回JSON
的休息服务:
{
"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<String, String> getBuildInfo(String buildUrl) {
return restTemplate.getForObject(buildUrl, Map.class);
}
以下是我设置restTemplate的方法:
@PostConstruct
public void initialize() {
List<ClientHttpRequestInterceptor> 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);
}
编辑II
完整的错误消息:
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]
答案 0 :(得分:12)
正如我之前所说,您的错误消息告诉我们您收到的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]
因此,杰克逊的MappingJackson2HttpMessageConverter
无法解析内容(它期待application/json
)。
原始答案:
假设您的HTTP响应Content-Type
为application/json
并且您在类路径中有杰克逊1或2,RestTemplate
可以将JSON反序列化为{{1} 1}}就好了。
如果您收到的错误已经完整显示,则您已经注册了自定义java.util.Map
对象,这些对象会覆盖默认对象,或者您没有杰克逊在您的类路径上,HttpMessageConverter
未注册(可以进行反序列化),或者您没有收到MappingJackson2HttpMessageConverter
。
答案 1 :(得分:11)
RestTemplate 有一个名为 exchange 的方法,该方法将 ParameterizedTypeReference 的实例作为参数。
要发出返回java.util.Map
的GET请求,只需创建一个继承自ParameterizedTypeReference的匿名类的实例。
ParameterizedTypeReference<HashMap<String, String>> responseType =
new ParameterizedTypeReference<HashMap<String, String>>() {};
然后您可以调用交换方法:
RequestEntity<Void> request = RequestEntity.get(URI("http://example.com/foo"))
.accept(MediaType.APPLICATION_JSON).build()
Map<String, String> jsonDictionary = restTemplate.exchange(request, responseType)
答案 2 :(得分:8)
更新02/05/2018(大约4年后)...我再次对此进行了测试,因为人们一直在回答我的问题/答案,Sotirios Delimanolis是正确的,我不应该写我的答案中的代码使这项工作。我使用了基本相同的RestTemplate / REST服务设置,如我的问题所示,REST服务具有确认的响应内容类型application / json,RestTemplate能够处理响应而没有问题进入Map。 强>
我最终将内容作为String
获取,然后将其转换为Map
,如下所示:
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;
答案 3 :(得分:2)
我认为您可以实现仅仅使用RestTemplate并指定JsonNode作为响应类型的目标。
ResponseEntity<JsonNode> response =
restTemplate.exchange(url, HttpMethod.GET, entity, JsonNode.class);
JsonNode map = response.getBody();
String someValue = map.get("someValue").asText();
答案 4 :(得分:0)
我知道它的旧版本,但仅适用于可能访问此主题的其他人: 如果要使用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;
}
答案 5 :(得分:0)
@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;
}
它对我有用...