亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為什么在序列化時 Json.Net 會在我的對象上調用 Equals 方法?

為什么在序列化時 Json.Net 會在我的對象上調用 Equals 方法?

C#
RISEBY 2021-11-14 14:33:56
我在使用 Newtonsoft.JsonSerializeObject方法時遇到了錯誤。之前有人問過這里,但與 Newtonsoft 合作的人沒有回答為什么會發生這種情況?;旧?,當這樣調用時SerializeObject:string json = Newtonsoft.Json.JsonConvert.SerializeObject(from, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All });我Equals在我的課程中覆蓋的許多方法中出現錯誤:public override bool Equals(object obj){    if (obj == null)        return false;    CapacityConfiguration cc = (CapacityConfiguration)obj; // <-- TypeCastException here; other Properties of the same class are sent in as parameter!}當然,我意識到通過這樣檢查來修復它很“容易”:public override bool Equals(object obj){    if (obj is CapacityConfiguration == false)        return false;    CapacityConfiguration cc = (CapacityConfiguration)obj;}但真正的問題是: 為什么Json.Net會在類的Equals方法中傳入其他類型的對象?更具體地說,Json.Net 似乎在類中發送了許多其他屬性,而不是另一個相同類型的對象。對我來說,這完全很奇怪。任何輸入將不勝感激。根據 Visual Studio,我正在使用“版本 8.0.0.0”。更新 1它很容易測試,因為它是可重現的:public class JsonTestClass{    public string Name { get; set; }    public List<int> MyIntList { get; set; }    public override bool Equals(object obj)    {        if (obj == null)            return false;        JsonTestClass jtc = (JsonTestClass)obj;        return true;    }}然后只需將此代碼放在 Program.cs 或其他任何地方:JsonTestClass c = new JsonTestClass();c.Name = "test";c.MyIntList = new List<int>();c.MyIntList.Add(1);string json = Newtonsoft.Json.JsonConvert.SerializeObject(c, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All });你會得到 TypeCast 異常:
查看完整描述

1 回答

?
慕的地8271018

TA貢獻1796條經驗 獲得超4個贊

為什么 JsonConvert.SerializeObject 會調用該object.Equals方法?


因為當你使用 時JsonConvert.SerializeObject,有一個方法CheckForCircularReference被調用來檢查一個屬性是否重新引用了你自己的對象,導致無限循環。


 private bool CheckForCircularReference(JsonWriter writer, object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty)

在CheckForCircularReference方法中,部分代碼使用了該Contains方法,object.Equals如果您object沒有實現該 IEquatable<T>接口,該方法將調用。


bool exists = (Serializer._equalityComparer != null)

                ? _serializeStack.Contains(value, Serializer._equalityComparer)

                : _serializeStack.Contains(value);

解釋


_serializeStack 是當前正在序列化的對象列表。

該List<T>.Contains方法檢查當前屬性是否包含在集合中。

List<T>.Containsuses EqualityComparer<T>.Default,IEquatable<T>如果類型實現它,則依次使用,object.Equals否則使用。

該object value參數是您當前的Property對象。

下面是一個自引用循環的例子:


public class JsonTestClass

{

    public string Name { get; set; }

    public List<int> MyIntList { get; set; }

    public JsonTestClass Test{get;set;}

    public override bool Equals(object obj)

    {

        if (obj == null)

            return false;

        JsonTestClass jtc = (JsonTestClass)obj;

        return true;

   }

}


JsonTestClass c = new JsonTestClass();

c.Name = "test";

c.Test = c;

string json = JsonConvert.SerializeObject

               (c, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All });

我們會得到一個異常:


檢測到類型為“Program+JsonTestClass”的屬性“test”的自引用循環。小路 ''。


但如果我們這樣做,就沒有錯誤:


JsonTestClass c = new JsonTestClass();

c.Name = "test";

c.Test = new JsonTestClass();


string json = JsonConvert.SerializeObject

       (c, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All });


查看完整回答
反對 回復 2021-11-14
  • 1 回答
  • 0 關注
  • 145 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號