Resttemplate getForObject map responsetype
Обновление 02/05/2018 (около 4 лет спустя)... Я проверил это снова, так как люди уже повысили мой вопрос/ответ, и Сотириос Делиманолис прав, что мне не нужно писать код в моем ответьте, чтобы сделать эту работу. Я использовал в основном ту же настройку службы RestTemplate/REST, как показано в моем вопросе, с помощью службы REST, имеющей подтвержденный тип содержимого ответа приложения /json, и RestTemplate смог обработать ответ без проблем на карте.
Я вызываю службу отдыха, которая возвращает 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
?
Изменить I
Здесь мой вызов 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]
Ответы
Ответ 1
Как я уже отмечал ранее, ваше сообщение об ошибке показывает нам, что вы получаете 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-Type
равен application/json
, и у вас есть Jackson 1 или 2 в пути к классам, RestTemplate
может десериализовать JSON, как вы, в java.util.Map
просто отлично.
С полученной вами ошибкой, которую вы не указали полностью, либо вы зарегистрировали пользовательские объекты HttpMessageConverter
, которые перезаписывают значения по умолчанию, либо у вас нет Jackson в вашем пути к классам, а MappingJackson2HttpMessageConverter
не регистрируется (что будет делать десериализация), или вы не получаете application/json
.
Ответ 2
Обновление 02/05/2018 (около 4 лет спустя)... Я проверил это снова, так как люди уже повысили мой вопрос/ответ, и Сотириос Делиманолис прав, что мне не нужно писать код в моем ответьте, чтобы сделать эту работу. Я использовал в основном ту же настройку службы RestTemplate/REST, как показано в моем вопросе, с помощью службы REST, имеющей подтвержденный тип содержимого ответа приложения /json, и RestTemplate смог обработать ответ без проблем на карте.
В итоге я получил содержимое как 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
RestTemplate имеет метод с именем exchange, который принимает экземпляр ParameterizedTypeReference как параметр.
Чтобы сделать запрос GET, который возвращает java.util.Map
, просто создайте экземпляр класса анонима, который наследует от 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)
Ответ 4
Я знаю его старый, но только для других людей, которые могут посетить эту тему:
Если вы хотите зарегистрировать некоторые дополнительные конвертеры с помощью 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
Я думаю, вы можете достичь того, чего хотите, просто используя RestTemplate и указав JsonNode в качестве типа ответа.
ResponseEntity<JsonNode> response =
restTemplate.exchange(url, HttpMethod.GET, entity, JsonNode.class);
JsonNode map = response.getBody();
String someValue = map.get("someValue").asText();