Why does Json.Net call the Equals method on my objects when serializing?

后端 未结 1 1522
盖世英雄少女心
盖世英雄少女心 2020-12-17 17:05

I just ran into an error when I was using the Newtonsoft.Json SerializeObject method. It has been asked before here, but there was no answer from the people wor

相关标签:
1条回答
  • 2020-12-17 17:32

    Why will JsonConvert.SerializeObject call the object.Equals method?

    Because when you use JsonConvert.SerializeObject, there is a method CheckForCircularReference which is called to check whether a property re-references your own object, leading to an infinite loop.

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

    In the CheckForCircularReference method, part of code uses the Contains method, which will call object.Equals if your object didn't implement the IEquatable<T> interface.

    bool exists = (Serializer._equalityComparer != null)
                    ? _serializeStack.Contains(value, Serializer._equalityComparer)
                    : _serializeStack.Contains(value);
    

    Explanation

    1. _serializeStack is a list of objects currently being serialized.
    2. The List<T>.Contains method checks whether the current property is or isn't contained in the collection.
    3. List<T>.Contains uses EqualityComparer<T>.Default, which in turn uses IEquatable<T> if the type implements it, or object.Equals otherwise.
    4. The object value parameter is your current Property object.

    Here is an example of a self-referencing loop:

    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 });
    

    We will get an exception:

    Self referencing loop detected for property 'test' with type 'Program+JsonTestClass'. Path ''.

    But if we do it like this there is no error:

    JsonTestClass c = new JsonTestClass();
    c.Name = "test";
    c.Test = new JsonTestClass();
    
    string json = JsonConvert.SerializeObject
           (c, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All });
    
    0 讨论(0)
提交回复
热议问题