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
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
_serializeStack
is a list of objects currently being serialized.List<T>.Contains
method checks whether the current property is or isn't contained in the collection.List<T>.Contains
uses EqualityComparer<T>.Default
, which in turn uses IEquatable<T>
if the type implements it, or object.Equals
otherwise.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 });