spring mvc踩坑 - jackson解析框架返回json多一层双引号

问题:

两套业务逻辑代码相同,但返回的数据不同,导致相同的前端代码用eval解析时出错。其中一个多了一层双引号,分别为

"{\"aaa\":1}"  "\"{\"aaa\":1}\""
//服务端代码
 @RequestMapping(method = RequestMethod.POST, params = "method=xxx")
    public
    @ResponseBody
    String xxx() {
        Result r = service.query();
        String result = JsonUtils.toJson(r);
        return result;
    }
//客户端代码
jQuery.post(url, data, function (result1) {
        if (result1 != "" && result1 != null) {
            var objs = eval('(' + result1 + ')');
            var myResult = eval('(' + objs + ')');
        }
    })	

解决思路:

  • 比较服务端业务代码:一致,且断点调试return的字符串相同,都是"{\"aaa\":1}"  
  • 比较前端代码:一致,且前端引擎都是velocity
  • 比较http协议:不一致,request头信息一致,但reponse头信息不一致,返回一层双引号的是 Content-Type:application/json;charset=UTF-8,返回两层双引号的是Content-type:text/html;charset=utf-8,于是怀疑有过滤器或拦截器修改了响应头信息
  • 查看过滤器和拦截器:两边一致,并且都没有修改响应头信息
  • 查看spring mvc的配置的json解析工具:都是jackson,但两个配置文件中supportedMediaTypes的顺序不一致,再考虑到响应头的不同,终于找到了问题的答案-Spring选择Converter是有优先级的(1、请求中的ContentType和Accept对应的Converter 2、如果1无法找到对应Converter,则通过遍历MessageConverters的canRead/canWrite选择最有可能的Converter  3、如果2无法找到对应Converter,则返回错误。)
//一层引号springmvc配置的json解析
<bean id="mappingJacksonHttpMessageConverter"
          class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
        <property name="supportedMediaTypes">
            <list>
                <value>application/json;charset=UTF-8</value>
                <value>text/html;charset=UTF-8</value>
            </list>
        </property>
    </bean>
    <mvc:annotation-driven>
        <mvc:message-converters>
            <ref bean="mappingJacksonHttpMessageConverter"/>
        </mvc:message-converters>
    </mvc:annotation-driven>
    

//两层引号springmvc配置的json解析
<bean id="mappingJacksonHttpMessageConverter"
          class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
        <property name="supportedMediaTypes">
            <list>
                <value>text/html;charset=UTF-8</value>
                <value>application/json;charset=UTF-8</value>
            </list>
        </property>
    </bean>

    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
            <util:list id="beanList">
                <ref bean="mappingJacksonHttpMessageConverter"/>
            </util:list>
        </property>
    </bean>

解决方案

  1. 修改spring mvc的配置文件,调整消息转换器的顺序
  2. 一层引号的版本,前端去掉一层eval函数
  3. 优化:
  • 服务端的JsonUtils.toJson()是多余的,因为spring mvc配置的json解析工具会自动序列化结果。
  • text/html;charset=UTF-8这种Content-Type会在数据外层包裹上一层双引号,如果返回的是string类型,则会出现两层双引号;返回Object,也会出现一层双引号,需要用eval来去除,或者在jQuery post() 方法指定预期的服务器响应的数据类型为'json';
//服务端代码
 @RequestMapping(method = RequestMethod.POST, params = "method=xxx")
    public
    @ResponseBody
    Object xxx() {
        Result r = service.query();
        Return r;
    }

//1、客户端代码(如果响应头是application/json;charset=UTF-8)
jQuery.post(url, data, function (result1) {
        if (result1 != "" && result1 != null) {
            var myResult = result1;
        }
    })	

//2、1 客户端代码(如果响应头是text/html;charset=UTF-8)
jQuery.post(url, data, function (result1) {
        if (result1 != "" && result1 != null) {
            var myResult = result1;
        }
    },'json')	

//2、2 客户端代码(如果响应头是text/html;charset=UTF-8)
jQuery.post(url, data, function (result1) {
        if (result1 != "" && result1 != null) {
            var myResult = eval('(' + result1+ ')');
        }
    })

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章