【发布时间】:2014-08-29 11:56:18
【问题描述】:
我正在使用 JSON.NET 6.0.3。我已将PreserveReferences 选项更改如下:
HttpConfiguration.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
我的对象图如下所示:
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 的 $ref ID。这不会发生。
尽管我找不到一篇说明如何为 ReferenceResolver 建立相等性的文档,但我已经实现了 IEquatable<CarManufacturer> 以及 base.Equals 和 base.GetHashCode() 的覆盖,但没有运气。
我想避免实现我自己的IReferenceResolver,因为在同一个项目中有非常相似的对象图按预期工作。
我唯一能想到的是我正在使用工厂对象,而不是先创建每个唯一的 CarManufacturer,然后创建 CarFromManufacturer 的实例,传入 CarManufacturer... 我正在创建一个新实例的CarManufacturer。这可以解释为什么对象不相等,但这就是我实现IEquatable 并覆盖base.Equals(object) 和base.GetHashCode() 的原因。
我查看了source for DefaultReferenceResolver,它使用default constructor of BidirectionalDictionary,它使用EqualityComparer<T>。默认情况下,来自MSDN documentation,使用T的实现IEquatable<T>(如果存在),否则使用T的@ 987654343@ 实现....所有这些都会让我相信CarManufacturer 中的IEquatable 应该可以解决我的问题。但是,在CarManufacturer.Equals() 和GethashCode() 中放置断点从未命中..
【问题讨论】:
-
我每次都创建制造商的新实例的原因是因为我的工厂对象接受了连接表记录的 EF 实体(连接汽车和制造商).. 所以它从EF Car 对象并使用 EF 制造商调用 ManufacturerFactory。
-
看起来对象引用被比较是否相等。实现
IReferenceResolver有什么问题? -
感谢您的考虑!重写 Equals 和 GetHashCode 是否不足以让 JSON.NET 的 DefaultReferenceResolver 知道如何比较对象?实现 IReferenceResolver 没有任何问题,只是如果不是因为这个问题,我就不需要额外的复杂性。我宁愿在这样做之前重组工厂代码。但问题实际上是关于 DefaultReferenceResolver 如何比较相等性。我正在更新帖子..
-
查看源码,相信默认使用this comparer,只比较引用
-
关于您的更新:
DefaultReferenceResolver致电JsonSerializerInternalBase.DefaultReferenceMappings。这个方法使用了我上面提到的比较器,没有使用BidirectionalDictionary的默认构造函数。
标签: c# asp.net-web-api json.net