resttemplate getForObject map responsetype

时间:2014-06-13 15:21:28

标签: java json spring resttemplate

更新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]

6 个答案:

答案 0 :(得分:12)

正如我之前所说,您的错误消息告诉我们您收到的application/octet-streamContent-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-Typeapplication/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;

    }

它对我有用...