SPRINGMVC parsing JSON data exceptions with Chinese characters

Source: Internet
Author: User

Recent development encountered a bug, the Exception log: Nested exception is org.codehaus.jackson.JsonParseException:Invalid UTF-8 start byte 0xbc, from the log can be seen, SPRINGMVC in parsing JSON data, found that JSON data is not utf-8 format, so I can not think of the results of the solution, so I went through the following series of attempts, took half a day to solve the bug.

Background:

The following information has been configured in Web. XML:

  <!--warranty request is utf-8--  <filter>    <filter-name>encoding</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>encoding</filter-name>    <url-pattern>/*</url-pattern>  </filter-mapping>

1, suspect is a client request, the data in the body is not using UTF-8 encoding

When this problem was encountered, the request was made using AJAX, the code is as follows:

$.ajax ({type: "POST", Url:url,async:true, ContentType: "Application/json; Charset=utf-8; ", data:JSON.stringify (data), DataType:" JSON ", Success:callback,error:function (XMLHttpRequest, Textstatus, Errorthrown) {console.log ("error:xmlhttprequest =" + Xmlhttprequest.responsetext); Console.log ("Error: Textstatus = "+ Errorthrown); Console.log (" Error:errorthrown = "+ Errorthrown);    });
Where data is: {"Mobileid": "Adea3fee77ef45949a82ab36ae83ec53", "Watchid": "9a4bc032ae564cc49bff5f976298de40", "type" : 1, "salutation": "Guardian"}, when salutation modified to English characters, request all normal, because here to contenttype understanding not confident, not sure ContentType set charset= Utf-8 guarantees the request, Httpbody code is utf-8 code, So stupid thought might be json.stringify this function in the serialization, caused by the encoding problem, thought json.stringify serialization, you can set the encoding format, a large number of Baidu after the failure to fail.

2. Write the Java application and submit the same request using HttpClient

The code is as follows:

    public static string DoPost (string URL, string body) {        HttpClient HC = Httpclientbuilder.create (). build ();        HttpPost post = new HttpPost (URL);        Post.addheader ("Content-type", "Application/json");        try {    stringentity stringentity = new Stringentity (Body, "UTF-8");    Post.setentity (stringentity);        } catch (Exception e) {         e.printstacktrace ();        }           HttpResponse response = null;        try {            response = Hc.execute (post);        Response.getstatusline (). Getstatuscode ();        String responsebody = entityutils.tostring (Response.getentity ());                System.out.println (responsebody);        Printhttpheaders (Response.getallheaders ());        return responsebody;                } catch (Exception e) {            e.printstacktrace ();            return null;        }    }
From the code, you can see
    Stringentity stringentity = new Stringentity (Body, "UTF-8");
Therefore, the parameter encoding in the Httpbody should be utf-8 encoding, unfortunately, the server still reported the same exception, but in this attempt, there is an unexpected harvest, when the request deployed on the Linux system Tomcat server, can succeed, Failed while requesting the Tomcat server on the native window.

3, suspicion is the problem of the server, this time the direction of the

With this doubt, the first suspicion is not what is tomcat on the configuration, can affect the SPRINGMVC JSON parsing, unfortunately, finally found that Tomcat does not have this configuration. Since it is the invalid UTF-8 start byte 0xbc, you can only determine that the byte value obtained by GetBytes () is incorrect when reading the body string. At this time, it is thought that the character encoding of GetBytes () is determined by what?

We know that getBytes also has this function: GetBytes (Charset Charset), since this is the case, then it means that Java has a default Charset to decide what the code is. Follow this idea, found Charset.defaultcharset (), the value of the output found in the window tomcat for: GBK, on Linux for Utf-8, no wonder there is no problem in Linux, there is a problem on the window, The value of the Defaultcharset is related to the environment in which the JVM is running, and the operating environment of the JVM is determined by the OS, and it is estimated that the JVM should be the encoding of the operating system.

However, when running a Java application written before in Eclipse on window, does the output really utf-8, does Defaultcharset not have an operating system encoding decision? The answer to this question is found in someone else's blog, because when running in eclipse, this is affected by eclipse, the JVM in Tomcat should still be affected by the operating system.

Now that you have found the cause, you can solve the bug, and here's the solution.

In fact, this bug caused by I in the filter, the body data is repackaged, mainly to filter the data in the body, so add a wrapper, if there is no this wrapper, the encoding should be no problem, the wrapper code in filter is as follows:

Class Bodyreaderhttpservletrequestwrapper extends Httpservletrequestwrapper {private final String bodystr;                Public Bodyreaderhttpservletrequestwrapper (HttpServletRequest request) throws IOException {super (Request);        Read the data in reader BufferedReader reader = Request.getreader ();        StringBuffer buffer = new StringBuffer ();        String line = null;        while (line = Reader.readline ())! = null) {buffer.append (line);    } bodystr = Buffer.tostring ();    } public String GetBody () {return bodystr; } @Override Public BufferedReader Getreader () throws IOException {return new BufferedReader (new Inputstr    Eamreader (getInputStream ())); } @Override Public ServletInputStream getInputStream () throws IOException {final Bytearrayinputstream ba is = new Bytearrayinputstream (bodystr.getbytes (<span style= "color: #FF0000;"        >charset.forname ("Utf-8") </span>)); REturn New ServletInputStream () {@Override public int read () throws IOException {            return Bais.read ();    }        }; }    }
Because here the bytes in the body read out programming bodystr, note the red part of the line of code, before there is a problem, did not addcharset.forname ("Utf-8"), because the default encoding on window is GBK, byte in natural new Bytearrayinputstream (Bodystr.getbytes ()) is encoded as GBK, so Filterchain.dofilter is called ( ServletRequest, response), the body code to reach the controller is GBK, resulting in the inability to parse the JSON data with the UTF-8 encoding, so there is a red part of the code, a smooth solution to the problem.

Incidentally there is a conjecture that, without validation, SPRINGMVC calls the corresponding JSON library to parse the body data, so it is determined by CharSet in the ContentType in Httpheader.


SPRINGMVC parsing JSON data exceptions with Chinese characters

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.