JsonConvert.SerializeObject将自定义类型属性传递给父类型Equals(对象)方法

本文关键字:类型 父类 Equals 对象 方法 SerializeObject 自定义 属性 JsonConvert | 更新日期: 2023-09-27 18:27:47

我看到一些奇怪的行为正在用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,而是CustomTypeProperty对象,然后是ListProperty,然后是List CustomProperty。在我的案例中,这会导致InvalidCastException,因为TestObject试图将obj参数强制转换为TestObject。我无法在现实世界的场景中更改这一点,因为类型在第三方库中。

这是Json.NET中的错误还是我做错了什么?我已经挖了一段时间,找不到任何解决办法。谢谢你的帮助。

编辑

我刚刚升级到Json.NET 6.0.6,看到了同样的行为。

JsonConvert.SerializeObject将自定义类型属性传递给父类型Equals(对象)方法

如果要实现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);
}

如果是第三方库在Equals方法中抛出了InvalidCastException,那么这肯定是一个错误。我会联系作者并要求他们修复它。

至于Json.Net为什么在对不同类型的对象进行序列化时调用Equals,这样做是为了检查引用循环。请参阅为什么Json.Net在序列化时对我的对象调用Equals方法?了解更多详细信息。