UTF-8 encoding problem in Spring MVC

JavaSpring MvcUtf 8Character Encoding

Java Problem Overview


I' ve a Spring MVC bean and I would like to return turkish character by setting encoding UTF-8. but although my string is "şŞğĞİıçÇöÖüÜ" it returns as "??????çÇöÖüÜ". and also when I look at the response page, which is internet explorer page, encoding is western european iso, not UTF-8.

Here is the code:

	@RequestMapping(method=RequestMethod.GET,value="/GetMyList")
public @ResponseBody String getMyList(HttpServletRequest request, HttpServletResponse response) throws CryptoException{
	String contentType= "text/html;charset=UTF-8";
	response.setContentType(contentType);
	try {
		request.setCharacterEncoding("utf-8");
	} catch (UnsupportedEncodingException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	response.setCharacterEncoding("utf-8");		
	String str="şŞğĞİıçÇöÖüÜ";
	return str;
}	

Java Solutions


Solution 1 - Java

I've figured it out, you can add to request mapping produces = "text/plain;charset=UTF-8"

@RequestMapping(value = "/rest/create/document", produces = "text/plain;charset=UTF-8")
@ResponseBody
public void create(Document document, HttpServletRespone respone) throws UnsupportedEncodingException {
	
	Document newDocument = DocumentService.create(Document);
	
	return jsonSerializer.serialize(newDocument);
}

see this blog post for more details on the solution

Solution 2 - Java

in your dispatcher servlet context xml, you have to add a propertie "<property name="contentType" value="text/html;charset=UTF-8" />" on your viewResolver bean. we are using freemarker for views.

it looks something like this:

<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
       ...
       <property name="contentType" value="text/html;charset=UTF-8" />
       ...
</bean>

Solution 3 - Java

Convert the JSON string to UTF-8 on your own.

@RequestMapping(value = "/example.json", method = RequestMethod.GET)
@ResponseBody
public byte[] example() throws Exception {

    return "{ 'text': 'äöüß' } ".getBytes("UTF-8");
}

Solution 4 - Java

In Spring 5, or maybe in earlier versions, there is MediaType class. It has already correct line, if you want to follow DRY:

public static final String APPLICATION_JSON_UTF8_VALUE = "application/json;charset=UTF-8";

So I use this set of controller-related annotations:

@RestController
@RequestMapping(value = "my/api/url", produces = APPLICATION_JSON_UTF8_VALUE)
public class MyController {
    // ... Methods here
}

It is marked deprecated in the docs, but I've run into this issue and it is better than copy-pastying the aforementioned line on every method/controller throughout your application, I think.

Solution 5 - Java

You need add charset in the RequestMapping annotation:

@RequestMapping(path = "/account",  produces = "application/json;charset=UTF-8")

Solution 6 - Java

There are some similar questions: https://stackoverflow.com/questions/6638284/spring-mvc-response-encoding-issue, https://stackoverflow.com/questions/5019162/custom-httpmessageconverter-with-responsebody-to-do-json-things.

However, my simple solution:

@RequestMapping(method=RequestMethod.GET,value="/GetMyList")
public ModelAndView getMyList(){
  String test = "čćžđš";
  ...
  ModelAndView mav = new ModelAndView("html_utf8");
  mav.addObject("responseBody", test);
}

and the view html_utf8.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>${responseBody}

No additional classes and configuration.
And You can also create another view (for example json_utf8) for other content type.

Solution 7 - Java

I've resolved this issue by inferring the produced return type into the first GET requestMethod. The important part here is the

produces="application/json;charset=UTF-8

So every one how use /account/**, Spring will return application/json;charset=UTF-8 content type.

@Controller
@Scope("session") 
@RequestMapping(value={"/account"}, method = RequestMethod.GET,produces="application/json;charset=UTF-8")
public class AccountController {

   protected final Log logger = LogFactory.getLog(getClass());

   ....//More parameters and method here...

   @RequestMapping(value={"/getLast"}, method = RequestMethod.GET)
   public @ResponseBody String getUltimo(HttpServletResponse response) throws JsonGenerationException, JsonMappingException, IOException{
	
	  ObjectWriter writer = new ObjectMapper().writer().withDefaultPrettyPrinter();
	  try {
		Account account = accountDao.getLast();
		return writer.writeValueAsString(account);
	  }
	  catch (Exception e) {
		return errorHandler(e, response, writer);
	  }
}

So, you do not have to set up for each method in your Controller, you can do it for the entire class. If you need more control over a specific method, you just only have to infer the produces return content type.

Solution 8 - Java

Also add to your beans :

   <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
	<property name="messageConverters">
		<array>
			<bean class="org.springframework.http.converter.StringHttpMessageConverter">
				<constructor-arg index="0" name="defaultCharset" value="UTF-8"/>
				<property name="supportedMediaTypes">
					<list>
						<value>text/plain;charset=UTF-8</value>
						<value>text/html;charset=UTF-8</value>
						<value>application/json;charset=UTF-8</value>
						<value>application/x-www-form-urlencoded;charset=UTF-8</value>
					</list>
				</property>
		</bean></bean>

For @ExceptionHandler :

enter code<bean class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver">
	<property name="messageConverters">
		<array>
			<bean class="org.springframework.http.converter.StringHttpMessageConverter">
				<constructor-arg index="0" name="defaultCharset" value="UTF-8"/>
				<property name="supportedMediaTypes">
					<list>
						<value>text/plain;charset=UTF-8</value>
						<value>text/html;charset=UTF-8</value>
						<value>application/json;charset=UTF-8</value>
						<value>application/x-www-form-urlencoded;charset=UTF-8</value>
					</list>
				</property>
			</bean>
			<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
				<property name="supportedMediaTypes">
					<list>
						<value>text/plain;charset=UTF-8</value>
						<value>text/html;charset=UTF-8</value>
						<value>application/json;charset=UTF-8</value>
						<value>application/x-www-form-urlencoded;charset=UTF-8</value>
					</list>
				</property>
			</bean>
		</array>
	</property>
</bean>

If you use <mvc:annotation-driven/> it should be after beans.

Solution 9 - Java

If you are using Spring MVC version 5 you can set the encoding also using the @GetMapping annotation. Here is an example which sets the content type to JSON and also the encoding type to UTF-8:

@GetMapping(value="/rest/events", produces = "application/json; charset=UTF-8")

More information on the @GetMapping annotation here:

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/GetMapping.html

Solution 10 - Java

When you try to send special characters like è,à,ù, etc etc, may be you see in your Jsp Post page many characters like '£','Ä’ or ‘Æ’. To solve this problem in 99% of cases you may move in your web.xml this piece of code at the head of file:

   <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

For complete example see here : https://lentux-informatica.com/spring-mvc-utf-8-encoding-problem-solved/

Solution 11 - Java

I found that "@RequestMapping produces=" and other configuration changes didn't help me. By the time you do resp.getWriter(), it is also too late to set the encoding on the writer.

Adding a header to the HttpServletResponse works.

@RequestMapping(value="/test", method=RequestMethod.POST)
public void test(HttpServletResponse resp) {
	try {
		resp.addHeader("content-type", "application/json; charset=utf-8");
        PrintWriter w = resp.getWriter();
        w.write("{\"name\" : \"μr μicron\"}");
        w.flush();
        w.close();
	} catch (Exception e) {
		e.printStackTrace();
	}
}

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
QuestionysnkyView Question on Stackoverflow
Solution 1 - JavaCharlie WuView Answer on Stackoverflow
Solution 2 - JavaakiView Answer on Stackoverflow
Solution 3 - JavarwitzelView Answer on Stackoverflow
Solution 4 - JavaXobotunView Answer on Stackoverflow
Solution 5 - JavaAndres GutierrezView Answer on Stackoverflow
Solution 6 - JavaTrungView Answer on Stackoverflow
Solution 7 - Javamiguel.angelView Answer on Stackoverflow
Solution 8 - JavaYura_danView Answer on Stackoverflow
Solution 9 - Javagil.fernandesView Answer on Stackoverflow
Solution 10 - JavaRosario MezzatestaView Answer on Stackoverflow
Solution 11 - JavaPaul CuddihyView Answer on Stackoverflow