今天在測試微信公衆號建立自定義菜單時,須要向微信的接口發送一段嵌套的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異常,所以設計了循環引用檢測的保護設計