JSON.NET序列化 - 如何DefaultReferenceResolver比较平等? [英] JSON.NET Serialization - How does DefaultReferenceResolver compare equality?

查看:183
本文介绍了JSON.NET序列化 - 如何DefaultReferenceResolver比较平等?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用JSON.NET 6.0.3。我已经改变PreserveReferences选项,如下所示:

I am using JSON.NET 6.0.3. I have changed PreserveReferences option as follows:

HttpConfiguration.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;



我的对象图如下所示:

My object graph resembles the following:

public class CarFromManufacturer
{
    public int CarID { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }
    public CarManufacturer Manufacturer { get; set; }
}

public class CarManufacturer
{
    public int ManufacturerID { get; set; }
    public string Name { get; set; }
}



我的WebAPI控制器,返回结果集的IEnumerable [CarFromManufacturer]的。所以结果可能是由两个唯一的制造商的对象5辆的列表。我期待JSON结果列出每个制造商只能在同一制造商的一次全面系列化,然后后续使用中参考编号美元的原始的$ ID。这没有发生。

My WebAPI controller is returning the result set of IEnumerable[CarFromManufacturer]. So the result could be a list of 5 cars from two unique manufacturer objects. I am expecting the JSON result to list each manufacturer only once fully serialized and then subsequent uses of the same Manufacturer to be $ref ID to the original's $id. That is not happening.

虽然我无法找到一个单件的文档的那谈到平等是如何建立的ReferenceResolver,我已经实现IEquatable随着没有运气base.Equals和base.GetHashCode()的覆盖。

Even though I can't find a single piece of documentation that speaks about how equality is established for the ReferenceResolver, I've implemented IEquatable along with override of base.Equals and base.GetHashCode() with no luck.

我想避免实现我自己的 IReferenceResolver 因为有非常相似的对象图如预期在同一个项目。

I'd like to avoid implementing my own IReferenceResolver because have very similar object graphs working as expected in the same project.

我能想到的唯一的事情是,我使用工厂对象并代替首先创建每一个独特的CarManufacturer,然后创建传递CarManufacturer的CarFromManufacturer的实例...我创建CarManufacturer的新实例。这可以解释为什么对象是不相等的,但是这就是为什么我实现IEquatable和base.Equals的覆盖(对象),base.GetHashCode()。

The only thing I can think of is that I am using factory objects and instead of creating each unique CarManufacturer first, then creating the instances of CarFromManufacturer passing in CarManufacturer... i am creating a new instance of the CarManufacturer. This would explain why the objects aren't equal, but that's why I implemented IEquatable and overrides of base.Equals(object) and base.GetHashCode().

我已经调查了源DefaultReferenceResolver 它使用的默认构造函数BidirectionalDictionary 它采用EqualityComparer.Default其中,从的 MSDN文档,采用T的实施IEquatable,如果它存在,或者以其他方式使用T的base.Equals()实现....这一切将导致我相信,在IEquatable应该CarManufacturer解决我的问题。但是,将断点CarManufacturer.Equals()和GetHashCode()从不打..

I've looked into the source for DefaultReferenceResolver and it uses the default constructor of BidirectionalDictionary which uses EqualityComparer.Default which, from MSDN documentation, uses the T's implementation of IEquatable if it exists, or otherwise uses T's base.Equals() implementation.... all of this would lead me to believe that IEquatable in CarManufacturer should fix my problem. However, placing breakpoints in CarManufacturer.Equals() and GethashCode() never hit..

推荐答案

JSON.NET的逻辑解析引用默认情况下,仅仅比较了使用此引用比较器

JSON.NET's logic for resolving references by default just compares references using this comparer.

如果你想以不同的方式来比较对象,你必须实现自定义的 IReferenceResolver

If you want to compare objects in a different manner, you'll have to implement a custom IReferenceResolver.

下面是接受一个的IEqualityComparer℃的例子; T> 来适应你的使用情况:

Here's an example that takes an IEqualityComparer<T> to accommodate your use case:

public class ReferenceResolver<T> : IReferenceResolver
{
    private Dictionary<string, T> stringToReference;
    private Dictionary<T, string> referenceToString;

    private int referenceCount;

    public ReferenceResolver(IEqualityComparer<T> comparer)
    {
        this.stringToReference = new Dictionary<string, T>();
        this.referenceToString = new Dictionary<T, string>(comparer);
        this.referenceCount = 0;
    }

    public void AddReference(
        object context,
        string reference,
        object value)
    {
        this.referenceToString.Add((T)value, reference);
        this.stringToReference.Add(reference, (T)value);
    }

    public string GetReference(
        object context,
        object value)
    {
        string result = null;

        if (!this.referenceToString.TryGetValue((T)value, out result))
        {
            referenceCount++;
            result = referenceCount.ToString(CultureInfo.InvariantCulture);

            this.referenceToString.Add((T)value, result);
            this.stringToReference.Add(result, (T)value);
        }

        return result;
    }

    public bool IsReferenced(
        object context,
        object value)
    {
        return this.referenceToString.ContainsKey((T)value);
    }

    public object ResolveReference(
        object context,
        string reference)
    {
        T r = default(T);

        this.stringToReference.TryGetValue(reference, out r);
        return r;
    }
}

这篇关于JSON.NET序列化 - 如何DefaultReferenceResolver比较平等?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆