最近在 StackOverFlow 解答一個很有趣的問題Json.Net / Newtonsoft: Using JsonConvert.SerializeObject results in weird .Equals calls - why?
問題簡述是:
使用Newtonsoft.Json.JsonConvert.SerializeObject
方法 來把物件轉成JSON
資料時,為什麼會呼叫物件的Equals
方法 且傳入的object obj
類型不是此類別類型,而是屬性的類型
以下是發問者提供的程式碼:
1 | public class JsonTestClass |
問題解析:
看到問題後我就直接去看Json.net原始碼 一探到底原因出在哪邊.
後面發現當我們在呼叫JsonConvert.SerializeObject
方法,會執行一個 private bool CheckForCircularReference私有方法.
1 | bool exists = (Serializer._equalityComparer != null) |
### 重點:
這個方法主要用意是判斷目前序列化JSON物件是否有重複引用本身,方法中有段程式碼使用到 List<T>.Contains
.
當我們在呼叫List<T>.Contains
時 預設EqualityComparer<T>.Default
進行比較來進行判斷是否存在集合中.
要寫客製化比較方式有兩種
- 在.net中每個類別都繼承於
Object
,Object
中有object.Equals
所以可以重寫object.Equals
方法. - 將此類別實現
IEquatable<T>
並重寫你要的比較方式.
所以會呼叫object.Equals
是因為上段程式碼
補充說明:
什麼是判斷目前序列化JSON物件是否有重複引用本身?
以下的範例是private bool CheckForCircularReference想要防止的問題
1 | public class JsonTestClass |
我們可以看到c.Test = c;
將自己本身付值給 public JsonTestClass Test{get;set;}
這個屬性.
我們執行上面程式碼會得到此錯誤
Self referencing loop detected for property ‘Test’ with type ‘Program+JsonTestClass’. Path ‘’.
是因為他要防止重複引用本身導致無限迴圈解析JSON
.
Note
預設值類型的比較是比較值.
預設參考類別比較的是地址.
此文作者:Daniel Shih(石頭)
此文地址: https://isdaniel.github.io/jsonconvert-serializeobject/
版權聲明:本博客所有文章除特別聲明外,均採用 CC BY-NC-SA 3.0 TW 許可協議。轉載請註明出處!