Java resttemplate getForObject 映射响应类型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24208828/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 10:49:53  来源:igfitidea点击:

resttemplate getForObject map responsetype

javajsonspringresttemplate

提问by Zack Macomber

Update 02/05/2018 (about 4 years later)...I tested this again as people have been upvoting my question/answer and Sotirios Delimanolis is correct that I should not have to write the code in my answer to make this work. I used basically the same RestTemplate/REST service setup as shown in my question with the REST service having a confirmed response content type of application/json and RestTemplate was able to process the response with no issues into a Map.

2018 年 2 月 5 日更新(大约 4 年后)......我再次测试了这一点,因为人们一直在支持我的问题/答案,Sotirios Delimanolis 是正确的,我不应该在我的答案中编写代码来完成这项工作。我使用了基本相同的 RestTemplate/REST 服务设置,如我的问题中所示,REST 服务具有应用程序/json 的确认响应内容类型,并且 RestTemplate 能够毫无问题地将响应处理到 Map 中。



I'm invoking a rest service that returns JSONlike this:

我正在调用一个返回JSON这样的休息服务:

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

I would like to think that I can invoke this service with a java.util.Mapas the response type but that's not working for me. I get this exception:

我想我可以使用 ajava.util.Map作为响应类型来调用此服务,但这对我不起作用。我得到这个例外:

org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [interface java.util.Map]

Should I just specify Stringas the response type and convert the JSONto a Map?

我应该只指定String为响应类型并将 the 转换JSON为 aMap吗?

Edit I

编辑我

Here's my restTemplate call:

这是我的 restTemplate 电话:

private Map<String, String> getBuildInfo(String buildUrl) {
    return restTemplate.getForObject(buildUrl, Map.class);
}

Here's how I'm setting up the restTemplate:

这是我设置 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);
}

Edit II

编辑二

Full error message:

完整的错误信息:

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]

采纳答案by Sotirios Delimanolis

As I had previously noted, your error message is showing us that you are receiving application/octet-streamas a Content-Type.

正如我之前所指出的,您的错误消息向我们表明您收到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]

As such, Hymanson's MappingHymanson2HttpMessageConvertercannot parse the content (it's expecting application/json).

因此,Hyman逊MappingHymanson2HttpMessageConverter无法解析内容(期待application/json)。



Original answer:

原答案:

Assuming your HTTP response's Content-Typeis application/jsonand you have have Hymanson 1 or 2 on the classpath, a RestTemplatecan deserialize JSON like you have into a java.util.Mapjust fine.

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

With the error you are getting, which you haven't shown in full, either you've registered custom HttpMessageConverterobjects which overwrite the defaults ones, or you don't have Hymanson on your classpath and the MappingHymanson2HttpMessageConverterisn't registered (which would do the deserialization) or you aren't receiving application/json.

对于您收到的错误,您没有完整显示,要么您注册了HttpMessageConverter覆盖默认对象的自定义对象,要么您的类路径上没有 Hymanson 并且MappingHymanson2HttpMessageConverter未注册(这将执行反序列化)或者您没有收到application/json.

回答by Zack Macomber

Update 02/05/2018 (about 4 years later)...I tested this again as people have been upvoting my question/answer and Sotirios Delimanolis is correct that I should not have to write the code in my answer to make this work. I used basically the same RestTemplate/REST service setup as shown in my question with the REST service having a confirmed response content type of application/json and RestTemplate was able to process the response with no issues into a Map.

2018 年 2 月 5 日更新(大约 4 年后)......我再次测试了这一点,因为人们一直在支持我的问题/答案,Sotirios Delimanolis 是正确的,我不应该在我的答案中编写代码来完成这项工作。我使用了基本相同的 RestTemplate/REST 服务设置,如我的问题中所示,REST 服务具有应用程序/json 的确认响应内容类型,并且 RestTemplate 能够毫无问题地将响应处理到 Map 中。



I ended up getting the contents as a Stringand then converting them to a Maplike this:

我最终将内容作为 aString然后将它们转换为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;

回答by WrRaThY

I know its old, but just for other people that may visit this topic: If you want to register some additional converters with RestTemplateBuilder you also have to explicitly register default ones

我知道它是旧的,但仅适用于可能访问此主题的其他人:如果您想使用 RestTemplateBuilder 注册一些额外的转换器,您还必须明确注册默认的

@Bean
public RestTemplateBuilder builder() {
    return new RestTemplateBuilder()
            .defaultMessageConverters()
            .additionalMessageConverters(halMessageConverter());
}

private HttpMessageConverter halMessageConverter() {
    ObjectMapper objectMapper = new ObjectMapper().registerModule(new Hymanson2HalModule());
    TypeConstrainedMappingHymanson2HttpMessageConverter halConverter = new TypeConstrainedMappingHymanson2HttpMessageConverter(ResourceSupport.class);
    halConverter.setSupportedMediaTypes(Collections.singletonList(MediaTypes.HAL_JSON));
    halConverter.setObjectMapper(objectMapper);
    return halConverter;
}

回答by JeremyW

RestTemplatehas a method named exchangethat takes an instance of ParameterizedTypeReferenceas parameter.

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

To make a GET request that returns a java.util.Map, just create an instance of an anonym class that inherits from ParameterizedTypeReference.

要发出返回 a 的 GET 请求java.util.Map,只需创建一个从 ParameterizedTypeReference 继承的匿名类的实例。

ParameterizedTypeReference<HashMap<String, String>> responseType = 
               new ParameterizedTypeReference<HashMap<String, String>>() {};

You can then invoke the exchange method:

然后您可以调用交换方法:

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

回答by riversidetraveler

I think you can achieve what you're aiming for simply using the RestTemplate and specifying a JsonNode as the response type.

我认为您只需使用 RestTemplate 并指定 JsonNode 作为响应类型即可实现您的目标。

    ResponseEntity<JsonNode> response = 
         restTemplate.exchange(url, HttpMethod.GET, entity, JsonNode.class);

    JsonNode map = response.getBody();

    String someValue = map.get("someValue").asText();