JSON.NET错误检测到类型的自回参考循环

我尝试序列化从实体数据模型.edmx自动生成的POCO类,以及何时使用

JsonConvert.SerializeObject 

我得到以下错误:

错误发生System.data.entity类型检测到的自回参考循环。

我该如何解决这个问题?


这是最好的解决方案http://code.msdn.microsoft.com/Loop-Reference-handling-in-caaffaf7

修复1:全局忽略循环引用

(我已经选择/尝试过这个,就像其他许多人一样)

json.net序列化程序可以选择忽略循环引用。 将下面的代码放入WebApiConfig.cs文件中:

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

简单的修复将使序列化程序忽略会导致循环的引用。 但是,它有局限性:

数据丢失循环引用信息该修补程序仅适用于JSON.net如果存在深度参考链,则无法控制引用的级别

如果您想在非api ASP.NET项目中使用此修补程序,则可以将以上行添加到Global.asax.cs ,但首先要添加:

var config = GlobalConfiguration.Configuration;

修复2:保留全局循环引用

第二个修复与第一个类似。 只需将代码更改为:

config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling 
     = Newtonsoft.Json.ReferenceLoopHandling.Serialize;     
config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling 
     = Newtonsoft.Json.PreserveReferencesHandling.Objects;

数据形状将在应用此设置后更改。

[
   {
      "$id":"1",
      "Category":{
         "$id":"2",
         "Products":[
            {
               "$id":"3",
               "Category":{
                  "$ref":"2"
               },
               "Id":2,
               "Name":"Yogurt"
            },
            {
               "$ref":"1"
            }
         ],
         "Id":1,
         "Name":"Diary"
      },
      "Id":1,
      "Name":"Whole Milk"
   },
   {
      "$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序列化器,并且可以为模型类提供更多的控制。


使用JsonSerializerSettings

  • 如果遇到参考循环,则ReferenceLoopHandling.Error (默认值)将会出错。 这就是为什么你会得到一个例外。
  • 如果对象是嵌套的,但不是无限制的,则ReferenceLoopHandling.Serialize非常有用。
  • 如果它是它自己的子对象,则ReferenceLoopHandling.Ignore不会序列化对象。
  • 例:

    JsonConvert.SerializeObject(YourPOCOHere, Formatting.Indented, 
    new JsonSerializerSettings { 
            ReferenceLoopHandling = ReferenceLoopHandling.Serialize
    });
    

    如果你必须序列化一个无限期嵌套的对象,你可以使用PreserveObjectReferences来避免StackOverflowException。

    例:

    JsonConvert.SerializeObject(YourPOCOHere, Formatting.Indented, 
    new JsonSerializerSettings { 
            PreserveReferencesHandling = PreserveReferencesHandling.Objects
    });
    

    选择你正在序列化的对象的意义。

    参考http://james.newtonking.com/json/help/


    修正是忽略循环引用,而不是序列化它们。 此行为在JsonSerializerSettings指定。

    带过载的单个JsonConvert

    JsonConvert.SerializeObject(YourObject, Formatting.Indented,
        new JsonSerializerSettings() {
            ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
        }
    );
    

    Global.asax.cs中的代码位于Application_Start()中的全局设置

    JsonConvert.DefaultSettings = () => new JsonSerializerSettings {
         Formatting = Newtonsoft.Json.Formatting.Indented,
         ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
    };
    

    参考:https://github.com/JamesNK/Newtonsoft.Json/issues/78

    链接地址: http://www.djcxy.com/p/20073.html

    上一篇: JSON.NET Error Self referencing loop detected for type

    下一篇: How can I parse JSON with C#?