我看到一些奇怪的行为,使用Json.NET v6.0.5为覆盖Equals方法的对象序列化,并且除了字符串之外还有引用类型属性。
public class TestObject
{
public ChildObject CustomTypeProperty
{
get;
set;
}
public List<string> ListProperty
{
get;
set;
}
public List<ChildObject> ListCustomProperty
{
get;
set;
}
public string StringProperty
{
get;
set;
}
public int IntProperty
{
get;
set;
}
public override bool Equals(object obj)
{
Console.WriteLine(obj.GetType().FullName);
return base.Equals(obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
public class ChildObject
{
}
然后我序列化它。
var testObj = new TestObject() { CustomTypeProperty = new ChildObject(), IntProperty = 1, ListCustomProperty = new List<ChildObject>(), ListProperty = new List<string>(), StringProperty = "abc" };
var json = JsonConvert.SerializeObject(testObj);
我可以看到它调用TestObject.Equals(object obj)三次并且不传入TestObject,而是传入CustomTypePropety对象,然后是ListProperty,然后是ListCustomProperty。在我的情况下,这会导致InvalidCastException,因为TestObject尝试将obj参数强制转换为TestObject。我无法在现实场景中更改此内容,因为该类型位于第三方库中。
这是Json.NET中的错误还是我做错了什么?我已经挖了一段时间,找不到任何解决方案。谢谢你的帮助。
修改
我刚刚升级到Json.NET 6.0.6并看到了相同的行为。
答案 0 :(得分:1)
如果要为bool Equals(object obj)
实现覆盖,则需要处理可能传递给您的任何类型。您无法假设呼叫者将始终传递您期望的类型。通常的解决方案是在投射之前进行简单的类型检查,如下所示:
public override bool Equals(object obj)
{
if (obj is TypeYouAreExpecting)
{
TypeYouAreExpecting other = (TypeYouAreExpecting) obj;
bool areEqual = false;
// implement your equals logic here
return areEqual;
}
return base.Equals(obj);
}
如果它是在InvalidCastException
方法中抛出Equals
的第三方库,那肯定是一个错误。我会联系作者并要求他们修复它。
至于为什么Json.Net在对不同类型的对象进行序列化时调用Equals
,这样做是为了检查引用循环。有关详细信息,请参阅Why does Json.Net call the Equals method on my objects when serializing?。