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

2023-12-12

我看到使用 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 中的错误还是我做错了什么?我已经挖掘了一段时间,找不到任何解决方案。谢谢您的帮助。

EDIT

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


如果您正在实施覆盖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 in the Equals方法,那绝对是一个bug。我会联系作者并要求他们修复它。

至于为什么 Json.Net 调用Equals在不同类型的对象序列化期间,这样做是为了检查引用循环。看为什么 Json.Net 在序列化时对我的对象调用 Equals 方法?更多细节。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JsonConvert.SerializeObject 将自定义类型属性传递给父类型 Equals(object) 方法 的相关文章

随机推荐