jgo*_*ein 16 c# json entity-framework json.net asp.net-web-api
我在使用Newtonsoft.Json从我的ASP.NET Web API控制器正确序列化数据时遇到问题.
这就是我的想法 - 如果我错了,请纠正我.在某些情况下(特别是当数据中没有任何循环引用时)一切都像您期望的那样 - 填充的对象列表被序列化并返回.如果我引入的数据导致模型中的循环引用(如下所述,甚至是PreserveReferencesHandling.Objectsset),则只有通过循环引用导致第一个对象的列表元素才能以客户端可以"使用"的方式进行序列化. ."元素导向"可以是数据中的任何元素,如果在将内容发送到序列化器之前以不同方式排序,但至少有一个元素将以客户端可以"使用"的方式序列化.空对象最终被序列化为Newtonsoft references({$ref:X}).
例如,如果我有一个EF模型,其导航属性如下所示:

在我的global.asax中:
var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
Run Code Online (Sandbox Code Playgroud)
这是我正在使用Entity Framework进行的基本查询(延迟加载已关闭,所以这里没有任何代理类):
[HttpGet]
[Route("starting")]
public IEnumerable<Balance> GetStartingBalances()
{
using (MyContext db = new MyContext())
{
var data = db.Balances
.Include(x => x.Source)
.Include(x => x.Place)
.ToList()
return data;
}
}
Run Code Online (Sandbox Code Playgroud)
到目前为止一直很好,data人口稠密.
如果没有循环引用,那么生命就是盛大的.但是,只要有2个Balance实体具有相同Source或者Place,那么序列化就会将Balance我返回的最顶层列表的后一个对象转换为Newtonsoft引用而不是它们的完整对象,因为它们已经在Balances属性中被序列化了所述的Source或Place(多个)对象:
[{"$id":"1","BalanceID":4,"SourceID":2,"PlaceID":2 ...Omitted for clarity...},{"$ref":"4"}]
Run Code Online (Sandbox Code Playgroud)
这个问题是,{$ref:4}即使我们人类了解正在发生的事情,客户也不知道该怎么做.在我的例子中,这意味着我不能使用AngularJS来ng-repeat覆盖我的整个Balances列表,因为它们不是所有Balance具有Balance要绑定属性的真实对象.我确信还有很多其他用例会出现同样的问题.
我无法关闭,json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects因为很多其他东西都会破坏(这在其他100个问题中有详细记载).
除了通过Web API控制器中的实体并执行此操作之外,还有更好的解决方法吗?
Balance.Source.Balances = null;
Run Code Online (Sandbox Code Playgroud)
所有导航属性打破循环引用?因为这似乎也不正确.
Bri*_*ers 19
是的,使用PreserveReferencesHandling.Objects是使用循环引用序列化对象图的最佳方法,因为它生成最紧凑的JSON,它实际上保留了对象图的引用结构.也就是说,当您将JSON反序列化回对象(使用理解$id和$ref表示法的库)时,对特定对象的每个引用都将指向该对象的同一实例,而不是具有相同数据的多个实例.
在您的情况下,问题是您的客户端解析器不理解Json.Net生成的符号$id和$ref符号,因此引用未被解析.这可以通过使用javascript方法在反序列化JSON后重建对象引用来修复.请参阅此处和此处的示例.
根据您的具体情况,可能有效的另一种可能性是设置ReferenceLoopHandling为Ignore序列化而不是设置PreserveReferencesHandling为Objects.但这不是一个完美的解决方案.有关使用和之间差异的详细说明,请参阅此问题.ReferenceLoopHandling.IgnorePreserveReferencesHandling.Objects
| 归档时间: |
|
| 查看次数: |
13732 次 |
| 最近记录: |