1. 程式人生 > >迴圈引用導致的json序列化失敗

迴圈引用導致的json序列化失敗

問題

昨天在給系統加日誌後,系統就一直報 Stack Overflow錯誤,找了很久才發現問題,引入的日誌工具使用 gson序列化,而列印的日誌物件裡包含迴圈引用,導致出錯。

簡單復現

/**
 * ClassName: SerializeModel <br/>
 * Function: 迴圈引用序列化<br/>
 * 迴圈引用:包括自迴圈,如本類和A、B互相引用 (感覺都是類設計的不好啊)
 *
 * stackOverflowError分析原因:當序列化引擎解析A時,它發現這個物件持有一個B的引用,轉而去解析B。解析B時,發現他又持有A的引用,又轉回A。如此產生StackOverflowError異常。
 *
 * @author gary.liu
 * @date 2018/9/23
 */
public class SerializeModel { private int id; private List<SerializeModel> models; public int getId() { return id; } public void setId(int id) { this.id = id; } public List<SerializeModel> getModels() { return models; } public
void setModels(List<SerializeModel> models) { this.models = models; } public String toString(){ return ToStringBuilder.reflectionToString(this); } public static void main(String[] args) { List<SerializeModel> models = Lists.newArrayList(); SerializeModel model =
new SerializeModel(); model.setId(1); models.add(model); model.setModels(models); System.out.println(ToStringBuilder.reflectionToString(model)); System.out.println(JSON.toJSONString(model)); System.out.println(JSON.toJSONString(ToStringBuilder.reflectionToString(model))); //下面會報stackoverflow error System.out.println(new Gson().toJson(model)); System.out.println(JSON.toJSON(model)); System.out.println(JSON.toJSONString(model, SerializerFeature.DisableCircularReferenceDetect)); } }

解決辦法

由於我只是想列印日誌,所以就只想到下面兩個辦法:

  1. 使用 ToStringBuilder.reflectionToString
  2. 使用 fastjson 的 JSON.toJSONString ,fastjson會預設迴圈引用處理成 $ref,不會報錯