舉個(gè)例子
HashMap map = new HashMap();
map.put("foo", map);
System.out.println(map);
輸出是:{foo=(this Map)}桑逝,this Map代表map自己引用自己赴背。
如果用fastjson序列換成json會(huì)怎么樣呢毛雇?
fastjson處理json序列化的方法都放在JSON類中烹困,主要有3個(gè)方法:
- toJSON()
- toJSONString()
- toJSONByteds()
toJSON()
HashMap map = new HashMap();
map.put("foo", map);
System.out.println(JSON.toJSON(map));
匯報(bào)異常Exception in thread "main" java.lang.StackOverflowError玄妈,原因跟toJSON實(shí)現(xiàn)方式有關(guān)
JSONObject json = new JSONObject(innerMap);
for (Map.Entry<Object, Object> entry : map.entrySet()) {
Object key = entry.getKey();
String jsonKey = TypeUtils.castToString(key);
Object jsonValue = toJSON(entry.getValue());//<--這里
json.put(jsonKey, jsonValue);
}
可以看到對(duì)Map的value還會(huì)調(diào)用toJSON方法,造成了死循環(huán)髓梅,且對(duì)value處理前任何配置都沒生效拟蜻,所以toJSON方法對(duì)循環(huán)引用無解。
嘗試一下toJSONString和toJSONBytes方法
HashMap map = new HashMap();
map.put("foo", map);
System.out.println(JSON.toJSONString(map));
System.out.println(new String(JSON.toJSONBytes(map)));
輸出:{"foo":{"$ref":"@"}}枯饿,跟直接print輸出一致酝锅。這兩個(gè)方法會(huì)依據(jù)配置SerializerFeature.DisableCircularReferenceDetect來控制是否開啟重復(fù)引用檢查,在處理value時(shí)判斷上下文中是否已經(jīng)存在對(duì)象奢方。如果開啟配置搔扁,且上下文中value對(duì)象已存在則用引用形式表示擒权。
//JavaBeanSerializer.class
public boolean writeReference(JSONSerializer serializer, Object object, int fieldFeatures) {
SerialContext context = serializer.context;
int mask = SerializerFeature.DisableCircularReferenceDetect.mask;
if (context == null || (context.features & mask) != 0 || (fieldFeatures & mask) != 0) {//<--這里
return false;
}
if (serializer.references != null && serializer.references.containsKey(object)) {
serializer.writeReference(object);
return true;
} else {
return false;
}
}
不同層級(jí)的引用會(huì)以不同的符號(hào)代替,具體可以參考JSONSerializer.writeReference()方法