FastJson 序列化出現"$ref"問題研究

今天在測試微信公衆號建立自定義菜單時,須要向微信的接口發送一段嵌套的json數據,在用FastJson對對象進行序列化時,發現出來的json字符串中始終存在"$ref",具體示例以下:json

Map<String,Object> cbtMap = new HashMap<>();
        cbtMap.put("key", "image");
        cbtMap.put("name", "回覆圖片");
        cbtMap.put("type","click");
        JSONObject cbtJson = new JSONObject(cbtMap);


        Map<String,Object> vbtMap = new HashMap<>();
        vbtMap.put("url", "http://www.cuiyongzhi.com");
        vbtMap.put("name", "博客");
        vbtMap.put("type","view");
        JSONObject vbtJson = new JSONObject(vbtMap);

        JSONArray subButton=new JSONArray();
        subButton.add(cbtJson);
        subButton.add(vbtJson);

        JSONObject buttonOne=new JSONObject();
        buttonOne.put("name", "菜單");
        buttonOne.put("sub_button", subButton);

        JSONArray button=new JSONArray();
        button.add(vbtJson);
        button.add(buttonOne);
        button.add(cbtJson);

        JSONObject menujson=new JSONObject();
        menujson.put("button", button);


        System.out.println(menujson.toJSONString());
複製代碼

出來的結果是這樣的: 瀏覽器

能夠看到,對於一個對象,當其首次出現時,FastJson的序列化是正常工做的,可是當其重複出現時,就會序列化實現,變爲對象的引用.能夠想到,這必定是FastJson內部存在一些特殊邏輯,因而上網查了查資料,問題產生的緣由在於FastJson存在循環/重複引用檢測特性,而且該特性是缺省開啓的bash

想要解決這個問題,很是簡單,只須要將原來的menujson.toJSONString()改成以下代碼:微信

// 禁用FastJson循環引用檢測功能(非全局)
JSON.toJSONString(menujson, SerializerFeature.DisableCircularReferenceDetect);
複製代碼

若是想要全局關閉該功能:性能

JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();
複製代碼

關閉該功能還會提升FastJson的性能哦測試

問題很快解決,可是不由會思考: FastJson要這個特性幹嘛用?ui

fastjson默認對json序列化的時候進行循環引用的檢測,從而避免了出現StackOverFlow異常。當序列化後的JSON傳輸到瀏覽器或者其餘語言中,這些json解析器不支持循環引用,從而致使數據丟失。url

疑問: 既然在不少場景下瀏覽器並不支持該功能,那麼爲甚麼還要把這個功能設置爲缺省開啓呢?spa

緣由在於,若是存在循環引用,頗有可能會出現SOF異常,所以設計了循環引用檢測的保護設計

相關文章
相關標籤/搜索