Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make spring boot default to application/json;charset=utf-8 instead of application/json;charset=iso-8859-1

I am updating spring-boot from 1.3.6 to 2.1.3 and while before responses had content type application/json;charset=UTF-8, now I am getting a charset of iso-8859-1.

I would like to have utf 8.

My controller looks like this:

@Controller
public class MyController {
    @RequestMapping(value={"/myService/{serviceId}"}, method=RequestMethod.POST, consumes="application/json")
    public ResponseEntity<Void> handlePostServiceId(final InputStream requestInputStream,
            @PathVariable String serviceId,
            final HttpServletRequest servletRequest,) {
       <$businessLogic>
       return new ResponseEntity<>(new HttpHeaders(), HttpStatus.ACCEPTED);
}

I can get it to return utf-8 if I include produces= MediaType.APPLICATION_JSON_UTF8_VALUE in my @RequestMapping but I would like to only have to set that once, rather than for every single API.

I also tried adding

@Override
    public void configureContentNegotiation(
         ContentNegotiationConfigurer configurer) {
         configurer.defaultContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
    }

to my WebMvcConfigurer as suggested here: https://stackoverflow.com/a/25275291/2855921 but that broke my availability api which consumes plain/text content type.

I also ensured that my request was UTF-8, so it is not just mirroring back the format I gave.

Any ideas on how I can set the charset to be UTF-8 for the entire project?

like image 261
pdewilde Avatar asked Apr 11 '19 20:04

pdewilde


People also ask

What is the default charset for application JSON?

The MIME media type for JSON text is application/json. The default encoding is UTF-8.

Why is APPLICATION_JSON_UTF8_VALUE deprecated?

APPLICATION_JSON_UTF8_VALUE. Deprecated. as of 5.2 in favor of APPLICATION_JSON_VALUE since major browsers like Chrome now comply with the specification and interpret correctly UTF-8 special characters without requiring a charset=UTF-8 parameter. A String equivalent of APPLICATION_JSON_UTF8 .

How can I pass UTF-8 in Postman?

Go into the "Headers" tab for the request and add a new header. Name it "Content-Type" (without the quotes) and set the value to "text/xml; charset=utf-8" (again, no quotes). Good luck! Thank you for this help, setting the header in the request.


2 Answers

Add the below properties to the application.properties file:

For Spring Boot 1.x

# Charset of HTTP requests and responses. Added to the "Content-Type" 
# header if not set explicitly.
spring.http.encoding.charset=UTF-8
# Enable http encoding support.
spring.http.encoding.enabled=true
# Force the encoding to the configured charset on HTTP requests and responses.
spring.http.encoding.force=true

Source: https://docs.spring.io/spring-boot/docs/1.5.22.RELEASE/reference/html/common-application-properties.html

For Spring Boot 2.x

server.servlet.encoding.charset=UTF-8
server.servlet.encoding.force-response=true

Source: https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#server.servlet.encoding.charset

like image 73
Bishal Jaiswal Avatar answered Nov 15 '22 22:11

Bishal Jaiswal


If you're using default object mapper (Jackson) then the encoding can be forced with this simple configuration:

    @Bean
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
        MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
        jsonConverter.setDefaultCharset(StandardCharsets.UTF_8);
        return jsonConverter;
    }

Here the MappingJackson2HttpMessageConverter() constructor uses public Jackson2ObjectMapperBuilder class to set default parameters for an object mapper.

For another object mapper (Gson or Jsonb) you can look into AllEncompassingFormHttpMessageConverter() constructor.

Note also MediaType.APPLICATION_JSON_UTF8 was deprecated in favor of MediaType.APPLICATION_JSON since Spring 5.2. So in tests I prefer to use contentTypeCompatibleWith(...) instead of contentType(..._UTF8):

        MvcResult result = mockMvc.perform(get("/api/resource"))
                .andDo(print())
                .andExpect(status().isOk())
                // .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
                .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
                .andReturn();

Links:

  • Commit where APPLICATION_JSON_UTF8 was replaced by APPLICATION_JSON in MappingJackson2HttpMessageConverter — https://github.com/spring-projects/spring-framework/commit/c38542739734c15e84a28ecc5f575127f25d310a
  • Chromium issue discussing "Content-Type: application/json" support —https://bugs.chromium.org/p/chromium/issues/detail?id=438464
  • No "charset" for "Content-Type: application/json" in RFC7159 — https://www.rfc-editor.org/rfc/rfc7159#section-11

More examples with MappingJackson2HttpMessageConverter:

  • Customizing HttpMessageConverters with Spring Boot and Spring MVC — https://dzone.com/articles/customizing
  • Http Message Converters with the Spring Framework — https://www.baeldung.com/spring-httpmessageconverter-rest
like image 38
oshatrk Avatar answered Nov 15 '22 21:11

oshatrk