作者:黄于諭春琪 | 来源:互联网 | 2022-12-08 18:28
我在使用Newtonsoft.Json SerializeObject
方法时遇到了一个错误.之前有人问过这个问题,但与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使用"Version 8.0.0.0".
更新1
它很容易测试,因为它是可重复的:
public class JsonTestClass
{
public string Name { get; set; }
public List 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();
c.MyIntList.Add(1);
string json = Newtonsoft.Json.JsonConvert.SerializeObject(c, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All });
你会得到TypeCast异常:
1> D-Shih..:
为什么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
接口,则会调用该方法.
bool exists = (Serializer._equalityComparer != null)
? _serializeStack.Contains(value, Serializer._equalityComparer)
: _serializeStack.Contains(value);
说明
_serializeStack
是当前正在序列化的对象列表.
该List.Contains
方法检查集合中是否包含当前属性.
List.Contains
使用EqualityComparer.Default
,IEquatable
如果类型实现它,则使用,object.Equals
否则.
该object value
参数是您当前的Property
对象.
以下是自引用循环的示例:
public class JsonTestClass
{
public string Name { get; set; }
public List 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 });
好吧,所以这是设计然后.对我来说足够好了.