C# 为什么Json.Net在序列化对象时调用Equals方法?
我在使用Newtonsoft.JsonC# 为什么Json.Net在序列化对象时调用Equals方法?,c#,json,json.net,equals,serialization,C#,Json,Json.net,Equals,Serialization,我在使用Newtonsoft.JsonSerializeObject方法时遇到了一个错误。以前有人问过这个问题,但是Newtonsoft的工作人员没有回答为什么会发生这种情况 基本上,当像这样调用SerializeObject时: string json = Newtonsoft.Json.JsonConvert.SerializeObject(from, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All
SerializeObject
方法时遇到了一个错误。以前有人问过这个问题,但是Newtonsoft的工作人员没有回答为什么会发生这种情况
基本上,当像这样调用SerializeObject
时:
string json = Newtonsoft.Json.JsonConvert.SerializeObject(from, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All });
public override bool Equals(object obj)
{
if (obj is CapacityConfiguration == false)
return false;
CapacityConfiguration cc = (CapacityConfiguration)obj;
}
我在类中重写的许多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!
}
但真正的问题是:
为什么Json.Net在类的Equals
方法中发送其他类型的对象?更具体地说,Json.Net似乎在类中发送了许多其他属性,而不是相同类型的另一个对象
对我来说,这太奇怪了。如有任何意见,将不胜感激
根据VisualStudio,我正在使用“Version8.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;
}
}
public类JsonTestClass
{
公共字符串名称{get;set;}
公共列表MyIntList{get;set;}
公共覆盖布尔等于(对象对象对象)
{
if(obj==null)
返回false;
JsonTestClass jtc=(JsonTestClass)obj;
返回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 });
JsonTestClass c=新的JsonTestClass();
c、 Name=“测试”;
c、 MyIntList=新列表();
c、 增加(1);
字符串json=Newtonsoft.json.JsonConvert.SerializeObject(c,新的JsonSerializerSettings(){TypeNameHandling=TypeNameHandling.All});
您将获得TypeCast异常:
为什么JsonConvert.SerializeObject会调用对象.Equals
方法
因为当您使用JsonConvert.SerializeObject
时,会调用一个方法来检查属性是否重新引用您自己的对象,从而导致无限循环
private bool CheckForCircularReference(JsonWriter writer, object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty)
在CheckForCircularReference
方法中,部分代码使用Contains
方法,该方法将调用对象。如果对象
未实现IEquatable
接口,则等于
bool exists = (Serializer._equalityComparer != null)
? _serializeStack.Contains(value, Serializer._equalityComparer)
: _serializeStack.Contains(value);
解释
\u serializeStack
是当前正在序列化的对象的列表
List.Contains
方法检查当前属性是否包含在集合中
List.Contains
使用EqualityComparer.Default
,如果类型实现了它,则使用IEquatable
,否则使用object.Equals
对象值
参数是您当前的属性
对象
以下是自引用循环的一个示例:
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 });
你能提供一个吗?这只是为了检测对象图中可能的循环吗?@LasseVågsætherKarlsen好吧,我还没有准备好,没有。我在我的大项目中转换一些数据时正在运行这个,所以我还没有做一个测试项目。我想也许有人可以解释一些众所周知的事情,但我会尝试做一个测试,看看是否可以在那里复制它。在任何情况下,可能的原因是json.net正在查看您是否正在序列化循环对象(直接引用自身的对象)。你的Equals(object)
方法应该准备好处理任何类型,所以不管json.net如何,这就是解决方法。我用上面的“UPDATE 1”更新了我的问题,很容易重现@拉塞夫·戈斯·瑟卡尔森:这是猜测还是你知道这是事实?因为我最初的想法是有一个严重的错误…?好吧,这是设计好的。对我来说足够好了。
JsonTestClass c = new JsonTestClass();
c.Name = "test";
c.Test = new JsonTestClass();
string json = JsonConvert.SerializeObject
(c, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All });