(轉)Json Self referencing loop

 


settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;html

 

修復2:保留全局循環引用

第二個修復與第一個相似。只需將代碼更改成:數據庫

   1: config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling
   2:      = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
   3: config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling
   4:      = Newtonsoft.Json.PreserveReferencesHandling.Objects;

 

https://blog.csdn.net/hanjun0612/article/details/59078428json

 

 

Self referencing loop detected......的錯誤app

 

解決方案:oop

1 增長  [JsonIgnore]  過濾關聯,使其不參與序列化。測試

這個方法簡單粗暴。可是你就沒辦法獲取關聯的json對象。this

 

2 序列化時,使用以下代碼,list是model對象(只適合關聯對象較少).net

(可是通過樓主測試,關聯比較多,比較複雜時,仍是沒卵用,直接卡死。這個問題的緣由呼之欲出,也是因爲主外鍵對象互相深度循環,牽涉到的實體層較多,關聯對象更多,就不贅述了)代理

JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
string result = JsonConvert.SerializeObject(list, settings);code

爲了引用方便,咱們能夠做爲擴展方法:
public static class Extension
{
public static string ToJsonString<T>(this T list)
{
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
string result = JsonConvert.SerializeObject(list, settings);
return result;
}
}

---------------------
做者:正怒月神
來源:CSDN
原文:https://blog.csdn.net/hanjun0612/article/details/59078428
版權聲明:本文爲博主原創文章,轉載請附上博文連接!

 

 

 


http://www.bubuko.com/infodetail-2525998.html

 

模型中有循環引用是很常見的。例如,如下模型顯示雙向導航屬性:

   1: public class Category 
   2: { 
   3:     public Category() 
   4:     { 
   5:         Products = new Collection<Product>(); 
   6:     } 
   7:     
   8:     public int Id { get; set; } 
   9:     public string Name { get; set; } 
  10:     public virtual ICollection<Product> Products { get; set; } 
  11: } 
  12:  
  13: public class Product 
  14: { 
  15:     public int Id { get; set; } 
  16:     public string Name { get; set; } 
  17:     public virtual Category Category { get; set; } 
  18: } 

經過生成EF API控制器與Web API一塊兒使用時,默認狀況下不起做用。使用json.net序列化器序列化時會發生如下錯誤:

Self referencing loop detected for property ‘Category‘ with type
‘System.Data.Entity.DynamicProxies.Category_A97AC61AD05BA6A886755C779FD3F96E86FE903ED7C9BA9400E79162C11BA719‘.
Path ‘[0].Products[0]‘

發生此錯誤是由於序列化程序不知道如何處理循環引用。(在xml序列化程序中也出現相似的錯誤)

禁用代理幷包含引用

EF代理不適用於POCO數據序列化。有幾種  解決方法。爲了簡單起見,咱們只是在數據上下文類中禁用它:

   1: public CircularReferenceSampleContext() : base("name=CircularReferenceSampleContext") 
   2: { 
   3:     Database.SetInitializer(new CircularReferenceDataInitializer()); 
   4:     this.Configuration.LazyLoadingEnabled = false; 
   5:     this.Configuration.ProxyCreationEnabled = false; 
   6: } 

可是,在禁用代理以後,導航屬性不會被延遲加載。所以,從數據庫中檢索數據時必須包含參考。將腳手架控制器代碼更改成: 

   1: public IEnumerable <Product> GetProducts()
   2: { 
   3:     return db.Products.Include(p => p.Category).AsEnumerable();
   4: } 

包含調用將包含全部記錄的參考數據。

修復1:全局忽略循環引用

json.net序列化器支持忽略全局設置的循環引用。一個快速解決方案是將下面的代碼放在WebApiConfig.cs文件中:

   1: config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

簡單的修復將使序列化程序忽略會致使循環的引用。可是,它有侷限性:

  • 數據丟失循環參考信息
  • 該修補程序僅適用於JSON.net
  • 若是存在深度參考鏈,則沒法控制參考級別

修復2:保留全局循環引用

第二個修復與第一個相似。只需將代碼更改成:

   1: config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling
   2:      = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
   3: config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling
   4:      = Newtonsoft.Json.PreserveReferencesHandling.Objects;

數據形狀將在應用此設置後更改。

   1: [{ 「$ ID」 :「1」 , 「類別」:{ 「$ ID」 :「2」 , 「產品」:[{ 「$ ID」 :「3」 , 「類別」:{ 「$ REF 「:」2「 },」ID「:2, 」 名稱「:」酸奶「 },{ 」$ REF「 :」1「 }],」ID「:1, 」 名稱「:」日記「 }, 」 Id「:1,「名稱」:「全脂牛奶」 },{ 「$ ref」:「3」 }]

$ id和$ ref保留全部引用,並使對象圖級別保持不變,但客戶端代碼須要知道形狀更改以消費數據,而且它僅適用於JSON.NET序列化程序。

修復3:忽略並保留參考屬性

此修補程序在模型類上裝飾屬性以控制模型或屬性級別上的序列化行爲。忽略該屬性:

   1: public class Category 
   2: { 
   3:     public int Id { get; set; } 
   4:     public string Name { get; set; } 
   5:     
   6:     [JsonIgnore] 
   7:     [IgnoreDataMember] 
   8:     public virtual ICollection<Product> Products { get; set; } 
   9: } 
 JsonIgnore用於JSON.NET,IgnoreDataMember用於XmlDCSerializer。 
爲了保持參考:
   1: // Fix 3 
   2: [JsonObject(IsReference = true)] 
   3: public class Category 
   4: { 
   5:     public int Id { get; set; } 
   6:     public string Name { get; set; } 
   7:  
   8:     // Fix 3 
   9:     //[JsonIgnore] 
  10:     //[IgnoreDataMember] 
  11:     public virtual ICollection<Product> Products { get; set; } 
  12: } 
  13:  
  14: [DataContract(IsReference = true)] 
  15: public class Product 
  16: { 
  17:     [Key] 
  18:     public int Id { get; set; } 
  19:  
  20:     [DataMember] 
  21:     public string Name { get; set; } 
  22:  
  23:     [DataMember] 
  24:     public virtual Category Category { get; set; } 
  25: } 

[JsonObject(IsReference = true)]適用於JSON.NET,[DataContract(IsReference = true)]適用於XmlDCSerializer。請注意:在類上應用DataContract後,您須要將DataMember添加到要序列化的屬性。

這些屬性能夠應用於json和xml序列化器,而且能夠爲模型類提供更多的控制。

參考官方解決方案:https://code.msdn.microsoft.com/Loop-Reference-handling-in-caaffaf7

相關文章
相關標籤/搜索