我在使用Newtonsoft.Json從我的ASP.NET Web API控制器正確序列化一些數據時遇到問題。如何「真的」用Newtonsoft.Json序列化循環引用對象?
這是我的認爲正在進行 - 請糾正我,如果我錯了。在某些情況下(特別是當數據中沒有任何循環引用時),所有內容都可以像您期望的那樣工作 - 將填充的對象列表序列化並返回。如果我在模型中引入了導致循環引用的數據(如下所述,並且即使設置了PreserveReferencesHandling.Objects
),也只有列表中帶有循環引用的第一個對象的列表元素被序列化,客戶端可以「與」。如果在將數據發送到序列化程序之前,「引導到的元素」可以是數據中的任何元素,但是至少有一個元素將以客戶端可以「使用」的方式進行序列化。空對象最終被序列化爲Newtonsoft引用({$ref:X}
)。
舉例來說,如果我有一個EF模型完整的導航性能,看起來像這樣:
在我的Global.asax:
var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
這裏的基本查詢我m使用實體框架(懶加載關閉,所以這裏沒有任何代理類):
[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;
}
}
到目前爲止好,data
已填充。
如果沒有循環引用,生活就是盛大。但是,只要存在具有相同Source
或Place
的實體,那麼序列化會將我返回到Newtonsoft引用的最頂級列表的後續對象變成Newtonsoft引用,而不是其完整對象,因爲它們已經是連載中Source
或Place
對象(S)的Balances
屬性:
[{"$id":"1","BalanceID":4,"SourceID":2,"PlaceID":2 ...Omitted for clarity...},{"$ref":"4"}]
這樣做的問題是客戶不知道做什麼用{$ref:4}
即使我們人類明白這是怎麼回事。在我的情況下,這意味着我無法使用AngularJS以ng-repeat
在我的整個天平列表中使用此JSON,因爲它們並非都是Balance
對象,而要綁定Balance
屬性。我敢肯定,還有很多其他使用案例會有相同的問題。
我無法關閉json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects
,因爲很多其他事情都會中斷(這裏有100個其他問題詳細記錄)。
是否有這更好的解決辦法除了通過在Web API控制器的實體去,做
Balance.Source.Balances = null;
到所有的導航性能,打破循環引用?因爲這看起來不正確。