How can I tell RestTemplate to POST with UTF-8 encoding?

JsonSpringResttemplate

Json Problem Overview


I'm having problems posting JSON with UTF-8 encoding using RestTemplate. Default encoding for JSON is UTF-8 so the media type shouldn't even contain the charset. I have tried to put charset in the MediaType but it doesn't seem to work anyway.

My code:

String dataJson = "{\"food\": \"smörrebröd\"}";
HttpHeaders headers = new HttpHeaders();
MediaType mediaType = new MediaType("application", "json", StandardCharsets.UTF_8);
headers.setContentType(mediaType);

HttpEntity<String> entity = new HttpEntity<String>(dataJson, headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Boolean> formEntity = restTemplate.exchange(postUrl, HttpMethod.POST, entity, Boolean.class);

Json Solutions


Solution 1 - Json

You need to add StringHttpMessageConverter to rest template's message converter with charset UTF-8. Like this

RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters()
        .add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));

Solution 2 - Json

(Adding to solutions by mushfek0001 and zhouji)

By default RestTemplate has ISO-8859-1 StringHttpMessageConverter which is used to convert a JAVA object to request payload.

Difference between UTF-8 and ISO-8859:

> UTF-8 is a multibyte encoding that can represent any Unicode > character. ISO 8859-1 is a single-byte encoding that can represent the > first 256 Unicode characters. Both encode ASCII exactly the same way.

Solution 1 (copied from mushfek001):
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters()
        .add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
Solution 2:

Though above solution works, but as zhouji pointed out, it will add two string converters and it may lead to some regression issues.

If you set the right content type in http header, then ISO 8859 will take care of changing the UTF characters.

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);

or

// HttpUriRequest request
request.addHeader("Content-Type", MediaType.APPLICATION_JSON_UTF8_VALUE);

Solution 3 - Json

The answer by @mushfek0001 produce two StringHttpMessageConverter which will send two text/plain and */*, such as the debug picture.

enter image description here

Even the Accept header of client will be:

text/plain, text/plain, */*, */*

So the better one is remove the ISO-8859-1 StringHttpMessageConverter and use single UTF-8 StringHttpMessageConverter.

Use this:

RestTemplate restTemplate = new RestTemplate();
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
stringHttpMessageConverter.setWriteAcceptCharset(true);
for (int i = 0; i < restTemplate.getMessageConverters().size(); i++) {
    if (restTemplate.getMessageConverters().get(i) instanceof StringHttpMessageConverter) {
        restTemplate.getMessageConverters().remove(i);
        restTemplate.getMessageConverters().add(i, stringHttpMessageConverter);
        break;
    }
}

Solution 4 - Json

Adding new StringHttpMessageConverter won't help. In existing StringHttpMessageConverter we need to set writeAcceptCharset to false and build httpheader with charset we want.

RestTemplate restTemplate = new RestTemplate();
   List<HttpMessageConverter<?>> c = restTemplate.getMessageConverters();
        for(HttpMessageConverter<?> mc :c){
            if (mc instanceof StringHttpMessageConverter) {
                StringHttpMessageConverter mcc = (StringHttpMessageConverter) mc;
                mcc.setWriteAcceptCharset(false);
            }
   }

  HttpHeaders headers = new HttpHeaders();
  headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
  headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8")));
  HttpEntity<String> entity = new HttpEntity<String>(jsonPayload, headers);

  restTemplate.postForEntity(postResourceUrl, entity, String.class);

Solution 5 - Json

restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(StandardCharsets.UTF_16LE));

String response = restTemplate.getForObject(url, String.class);

Solution 6 - Json

Removing the existing converter, but with Java 8 (why do people still write Java 7 Code anyways?)

List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
converters.removeIf(httpMessageConverter -> httpMessageConverter instanceof StringHttpMessageConverter);
converters.add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));

Solution 7 - Json

Better you should remove the StringHttpMessageConverter first before adding new. so this way you will have one instance of StringHttpMessageConverter in our MessageConverters list.

RestTemplate restTemplate = new RestTemplate();
		final Iterator<HttpMessageConverter<?>> iterator = restTemplate.getMessageConverters().iterator();
	    while (iterator.hasNext()) {
	        final HttpMessageConverter<?> converter = iterator.next();
	        if (converter instanceof StringHttpMessageConverter) {
	            iterator.remove();
	        }
	    }
		
		
		restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));

Solution 8 - Json

Try this

restTemplate.getMessageConverters().set(1,new StringHttpMessageConverter(Charsets.UTF_8));

Solution 9 - Json

If you're using Spring Boot it will auto-configure RestTemplate with a high-priority UTF-8 charset StringHttpMessageConverter, if you use RestTemplateBuilder to create the RestTemplate instance. E.g. restTemplateBuilder.build()

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionanssiasView Question on Stackoverflow
Solution 1 - Jsonmushfek0001View Answer on Stackoverflow
Solution 2 - JsonRohitView Answer on Stackoverflow
Solution 3 - JsonzhoujiView Answer on Stackoverflow
Solution 4 - JsonSandeshView Answer on Stackoverflow
Solution 5 - JsonRan AdlerView Answer on Stackoverflow
Solution 6 - JsonMichel JungView Answer on Stackoverflow
Solution 7 - Jsonpankaj desaiView Answer on Stackoverflow
Solution 8 - JsonaqiaoView Answer on Stackoverflow
Solution 9 - JsonAndy BirchallView Answer on Stackoverflow