31

I'm using the Java Spring Resttemplate for getting a json via a get request. The JSON I'm getting has instead of special character slike ü ö ä or ß some weird stuff. So I guess somethings wrong with the character encoding. I can't find any help on the internet. The code I'm using for now is:

String json = restTemplate.getForObject(
    overPassStatementPostCode,
    String.class,
    params);
Honza Zidek
  • 9,204
  • 4
  • 72
  • 118
Shachty
  • 521
  • 2
  • 7
  • 16
  • What is overPassStatementPostCode? Please post more code, including your corresponding POJO. – Martin McKeaveney Dec 22 '14 at 13:55
  • 1
    You are setting `String.class` which will use `StringHttpMessageConverter`. Can you try to use `MappingJackson2HttpMessageConverter`. E.g. ` ArrayList> messageConverters = new ArrayList>(); messageConverters.add(new MappingJackson2HttpMessageConverter()); restTemplate.setMessageConverters(messageConverters); ` – sol4me Dec 22 '14 at 13:58
  • 1
    Looking at the source code , we can also pass charset to StringHttpMessageConverter(),you can pass it `UTF-8` charset because defaultCharSet is `ISO-8859-1` – sol4me Dec 22 '14 at 14:05
  • Sorry, but I can't understand how to set the charSet in the code. The overPassStamementPostCode is just a string with placeholders. It gets filled with the parameters in the params Map. – Shachty Dec 29 '14 at 08:54
  • I can create a StringMessageConverter with a code like this : StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(Charset.forName("UTF-8")); but I just can't find a way how to use his converter with my http get request. Thank you for your help. – Shachty Dec 29 '14 at 09:24

6 Answers6

95

You just need to add the StringHttpMessageConverter to the template's message converters:

RestTemplate template = new RestTemplate();
template.getMessageConverters()
        .add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
ResponseEntity<Object> response = template.exchange(endpoint, method, entity, 
                                                    Object.class);
beerbajay
  • 19,652
  • 6
  • 58
  • 75
  • 1
    Solved [my encoding](http://stackoverflow.com/questions/28481118/utf-8-encoded-characters-from-rest-query-not-rendered-properly) problem. If you want the bounty, please write the answer there. Otherwise I will link it here and write own answer. – john May 21 '15 at 18:36
  • 3
    Your post just ended 2 hours of pulling my hairs out, thanks man – salgmachine Aug 12 '16 at 13:29
  • 1
    Greetings from the year 2018. Just came by to tell you I love you for solving my problem! – Alex Eggers Dec 04 '18 at 12:22
  • Apparently the index is important. It did not work without the 0 for me. – Thomas Feb 08 '19 at 09:41
  • @beerbajay: I come across an issue while using this approach. If we use DI(dependency injection) for `RestTemplate` in spring and use this approach to encode UTF-8 then we get `Encountered Exception during request : java.util.ConcurrentModificationException`. *Is there any better solution for this!* – Prabal Srivastava Mar 21 '19 at 07:54
  • Prabal, this error is because you´re trying to add to the messageConverters list concurrently with other threads reading from it. The correct approach would be to add this converter in the @Configuration class you use to set your RestTemplate – Tomaz Fernandes Apr 24 '19 at 20:16
  • I just used it with a KeycloakRestTemplate and a general RestTemplate. it works just fine. Thank you very much. I recommend to keep it an a central place like mentioned in the @Configuration Class within the Injected RestTemplate Bean. – FishingIsLife Jan 20 '20 at 12:03
  • it's not working if I creating rest template with HttpComponentsClientHttpRequestFactory – madhusudhan Oct 29 '20 at 18:01
1

First I tried @beerbajay 's way , but it not helps。 Finally I resolve it by below way

        RestTemplate template = new RestTemplate();
//      template.getMessageConverters()
//              .add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(newArrayList(MediaType.APPLICATION_JSON));
        ResponseEntity<String> response = template.exchange(url, HttpMethod.GET, new HttpEntity<String>(headers), String.class);
zhuguowei
  • 8,401
  • 16
  • 70
  • 106
1

I've same issue on this case, after one search, I've got this link: https://gist.github.com/knight1128/66f3e4817ab35c7397fd

its workaround is working for me:

package com.google.locationlab;

import com.google.common.collect.Lists;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Test;
import org.springframework.http.*;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;
import java.nio.charset.Charset;
import java.util.List;

public class PortalRestTemplateIntegrationTest {
    private Log logger = LogFactory.getLog(PortalRestTemplateIntegrationTest.class);

    @Test
    public void test() throws Exception {
        RestTemplate restTemplate = new RestTemplate();

        HttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
        List<HttpMessageConverter<?>> httpMessageConverter = Lists.newArrayList();
        httpMessageConverter.add(stringHttpMessageConverter);
        restTemplate.setMessageConverters(httpMessageConverter);

        URI targetUrl= UriComponentsBuilder.fromUriString("http://portal.net")
                .path("search")
                .queryParam("q", "잠실역")
                .build()
                .toUri();

        HttpHeaders headers = new HttpHeaders();
        Charset utf8 = Charset.forName("UTF-8");
        MediaType mediaType = new MediaType("text", "html", utf8);
        headers.setContentType(mediaType);
        headers.set("User-Agent", "mozilla");
        headers.set("Accept-Language", "ko"); 
        // gzip 사용하면 byte[] 로 받아서, 압축을 풀고 decoding 해야 한다. 

        HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
        ResponseEntity<String> responseEntity = restTemplate.exchange(targetUrl.toURL().toString(), HttpMethod.GET, entity, String.class);
        String result = responseEntity.getBody();

        logger.info(result);

    }
}
KentChow
  • 11
  • 2
0

I have solved this problem. I need to POST a string object in request body with UTF-8.

text/plain

httpHeaders.setContentType(new MediaType("text", "plain", StandardCharsets.UTF_8));

applicaton/json

httpHeaders.setContentType(new MediaType("applicaton", "json", StandardCharsets.UTF_8));

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> resposeEntity = null;

HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(new MediaType("text", "plain", StandardCharsets.UTF_8));

HttpEntity<String> httpEntity = new HttpEntity<String>(stringContent, httpHeaders);
responseEntity = restTemplate.exchange(requestUrl, HttpMethod.POST, httpEntity, String.class);

if (HttpStatus.OK.equals(responseEntity.getStatusCode())) {
    logger.debug("... success ... result: " + responseEntity.getBody());
}
0

You can still use String.class as a response type if you can do the following.

Upgrading to spring-web 5.2 solves the problem. or set writeAcceptCharset property to false belongs to StringHttpMessageConverter and use that convertor further in RestTemplate instance.

boolean writeAcceptCharSet = false;
List<HttpMessageConverter<?>> c = restTemplate.getMessageConverters();
for (HttpMessageConverter<?> mc : c) {
  if (mc instanceof StringHttpMessageConverter) {
    StringHttpMessageConverter mcc = (StringHttpMessageConverter) mc;
    mcc.setWriteAcceptCharset(writeAcceptCharSet);
  }
}
Bhukailas
  • 47
  • 7
0

In my case, I was using Postman. It was sending a hidden header of:

Accept-Encoding: gzip, deflate, br

I removed this header and my response came back correctly, instead of mumbo-jumbos.

henrykodev
  • 2,964
  • 3
  • 27
  • 39