36

I'm using the Java Spring RestTemplate for getting a JSON via a get request. The JSON I'm getting has instead of special characters like ü ö ä or ß some weird stuff. So I guess something is 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);
5
  • What is overPassStatementPostCode? Please post more code, including your corresponding POJO. Commented Dec 22, 2014 at 13:55
  • 1
    You are setting String.class which will use StringHttpMessageConverter. Can you try to use MappingJackson2HttpMessageConverter. E.g. ` ArrayList<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>(); messageConverters.add(new MappingJackson2HttpMessageConverter()); restTemplate.setMessageConverters(messageConverters); ` Commented Dec 22, 2014 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 Commented Dec 22, 2014 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. Commented Dec 29, 2014 at 8: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. Commented Dec 29, 2014 at 9:24

6 Answers 6

98

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);
Sign up to request clarification or add additional context in comments.

6 Comments

Solved my encoding problem. If you want the bounty, please write the answer there. Otherwise I will link it here and write own answer.
Apparently the index is important. It did not work without the 0 for me.
@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, 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
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.
|
3

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

    }
}

1 Comment

Is StandardCharsets.UTF_8 better than Charset.forName("UTF-8")?
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);

Comments

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

Comments

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

Comments

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.