wake-up-neo.com

antwortvorlage für getForObject-Map

Update 02/05/2018 (ca. 4 Jahre später) ... Ich habe das noch einmal getestet, da die Leute meine Frage/Antwort auf den neuesten Stand gebracht haben und Sotirios Delimanolis richtig ist, dass ich den Code in meiner Antwort nicht schreiben muss mach das klappen Ich habe im Wesentlichen das gleiche RestTemplate/REST-Service-Setup verwendet, das in meiner Frage mit dem REST -Dienst mit einem bestätigten Antwort-Inhaltstyp/json angegeben ist, und RestTemplate konnte die Antwort ohne Probleme in eine Map verarbeiten.


Ich rufe einen Ruhedienst auf, der JSON wie folgt zurückgibt:

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

Ich würde gerne glauben, dass ich diesen Service mit einem Java.util.Map als Antworttyp aufrufen kann, aber das funktioniert nicht für mich. Ich bekomme diese Ausnahme:

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

Soll ich nur String als Antworttyp angeben und die JSON in eine Map umwandeln? 

Editiere ich

Hier ist mein restTemplate-Aufruf:

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

So richten Sie die restTemplate ein:

@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);
}

Bearbeiten II

Vollständige Fehlermeldung:

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]
14
Zack Macomber

Wie bereits erwähnt, zeigt Ihre Fehlermeldung an, dass Sie application/octet-stream als Content-Type empfangen.

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]

Daher kann Jacksons MappingJackson2HttpMessageConverter den Inhalt nicht analysieren (er erwartet application/json).


Ursprüngliche Antwort:

Wenn Sie davon ausgehen, dass Content-Type Ihrer HTTP-Antwort application/json ist und Sie über Jackson 1 oder 2 im Klassenpfad verfügen, kann eine RestTemplate JSON wie in einem Java.util.Map deserialisieren.

Bei dem Fehler, den Sie nicht vollständig angezeigt haben, haben Sie entweder benutzerdefinierte HttpMessageConverter-Objekte registriert, die die Standardwerte überschreiben, oder Sie haben Jackson nicht in Ihrem Klassenpfad, und der MappingJackson2HttpMessageConverter ist nicht registriert (was der Fall wäre.) Deserialisierung durchführen) oder Sie erhalten application/json nicht.

11

RestTemplate hat eine Methode namens exchange, die eine Instanz von ParameterizedTypeReference als Parameter verwendet.

Erstellen Sie zum Erstellen einer GET-Anforderung, die einen Java.util.Map zurückgibt, eine Instanz einer anonymen Klasse, die von ParameterizedTypeReference erbt.

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

Sie können dann die Austauschmethode aufrufen: 

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

Update 02/05/2018 (ca. 4 Jahre später) ... Ich habe das noch einmal getestet, da die Leute meine Frage/Antwort auf den neuesten Stand gebracht haben und Sotirios Delimanolis richtig ist, dass ich den Code in meiner Antwort nicht schreiben muss mach das klappen Ich habe im Wesentlichen das gleiche RestTemplate/REST-Service-Setup verwendet, das in meiner Frage mit dem REST -Dienst mit einem bestätigten Antwort-Inhaltstyp/json angegeben ist, und RestTemplate konnte die Antwort ohne Probleme in eine Map verarbeiten.


Am Ende bekam ich die Inhalte als String und konvertierte sie dann in eine Map wie folgt:

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;
8
Zack Macomber

Ich denke, Sie können erreichen, was Sie erreichen möchten, indem Sie einfach das RestTemplate verwenden und einen JsonNode als Antworttyp angeben. 

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

    JsonNode map = response.getBody();

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

Ich weiß, dass es alt ist, aber nur für andere Personen, die dieses Thema besuchen: Wenn Sie zusätzliche Konverter bei RestTemplateBuilder registrieren möchten, müssen Sie auch die Standardkonvertierungen explizit registrieren

@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;
}
0
WrRaThY