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+ ')');
        }
    })

 

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