检测到类型的 JSON.NET 错误自引用循环 [英] JSON.NET Error Self referencing loop detected for type

查看:42
本文介绍了检测到类型的 JSON.NET 错误自引用循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

JsonConvert.SerializeObject

我收到以下错误:

<块引用>

检测到类型 System.data.entity 的错误自引用循环发生.

我该如何解决这个问题?

解决方案

那是最好的解决方案https://docs.microsoft.com/en-us/archive/blogs/hongyes/loop-reference-handling-in-web-api

修复 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;

如果你想在 .Net Core 项目中使用它,你可以将 Startup.cs 更改为:

 var mvc = services.AddMvc(options =>{...}).AddJsonOptions(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);

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

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

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

应用此设置后,数据形状将发生变化.

<预><代码>[{$id":1",类别":{$id":2",产品":[{$id":3",类别":{$ref":2"},ID":2,名称":酸奶"},{$ref":1"}],Id":1,名称":日记"},Id":1,名称":全脂牛奶"},{$ref":3"}]

$id 和 $ref 保留所有引用并使对象图级别平坦,但客户端代码需要知道形状更改以使用数据,并且它也仅适用于 JSON.NET 序列化程序.

修复 3:忽略并保留引用属性

此修复是在模型类上装饰属性以控制模型或属性级别的序列化行为.忽略该属性:

 公共类类别{公共 int Id { 获取;放;}公共字符串名称 { 获取;放;}[Json忽略][忽略数据成员]公共虚拟 ICollection<Product>产品{得到;放;}}

JsonIgnore 用于 JSON.NET,IgnoreDataMember 用于 XmlDCSerializer.保留参考:

//修复 3[JsonObject(IsReference = true)]公开课类别{公共 int Id { 获取;放;}公共字符串名称 { 获取;放;}//修复 3//[Json忽略]//[忽略数据成员]公共虚拟 ICollection<Product>产品{得到;放;}}[数据合同(IsReference = true)]公开课产品{[钥匙]公共 int Id { 获取;放;}[数据成员]公共字符串名称 { 获取;放;}[数据成员]公共虚拟类别类别{获取;放;}}

JsonObject(IsReference = true)] 用于 JSON.NET 而 [DataContract(IsReference = true)] 用于 XmlDCSerializer.注意:在类上应用DataContract后,需要在需要序列化的属性中添加DataMember.

属性可以应用于 json 和 xml 序列化程序,并提供对模型类的更多控制.

I tried to serialize POCO class that was automatically generated from Entity Data Model .edmx and when I used

JsonConvert.SerializeObject 

I got the following error:

Error Self referencing loop detected for type System.data.entity occurs.

How do I solve this problem?

解决方案

That was the best solution https://docs.microsoft.com/en-us/archive/blogs/hongyes/loop-reference-handling-in-web-api

Fix 1: Ignoring circular reference globally

(I have chosen/tried this one, as have many others)

The json.net serializer has an option to ignore circular references. Put the following code in WebApiConfig.cs file:

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

The simple fix will make serializer to ignore the reference which will cause a loop. However, it has limitations:

  • The data loses the looping reference information
  • The fix only applies to JSON.net
  • The level of references can't be controlled if there is a deep reference chain

If you want to use this fix in a non-api ASP.NET project, you can add the above line to Global.asax.cs, but first add:

var config = GlobalConfiguration.Configuration;

If you want to use this in .Net Core project, you can change Startup.cs as:

  var mvc = services.AddMvc(options =>
        {
           ...
        })
        .AddJsonOptions(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);

Fix 2: Preserving circular reference globally

This second fix is similar to the first. Just change the code to:

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

The data shape will be changed after applying this setting.

[
   {
      "$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"
   }
]

The $id and $ref keeps the all the references and makes the object graph level flat, but the client code needs to know the shape change to consume the data and it only applies to JSON.NET serializer as well.

Fix 3: Ignore and preserve reference attributes

This fix is decorate attributes on model class to control the serialization behavior on model or property level. To ignore the property:

 public class Category 
    { 
        public int Id { get; set; } 
        public string Name { get; set; } 
       
        [JsonIgnore] 
        [IgnoreDataMember] 
        public virtual ICollection<Product> Products { get; set; } 
    } 

JsonIgnore is for JSON.NET and IgnoreDataMember is for XmlDCSerializer. To preserve reference:

 // Fix 3 
        [JsonObject(IsReference = true)] 
        public class Category 
        { 
            public int Id { get; set; } 
            public string Name { get; set; } 
         
           // Fix 3 
           //[JsonIgnore] 
           //[IgnoreDataMember] 
           public virtual ICollection<Product> Products { get; set; } 
       } 
        
       [DataContract(IsReference = true)] 
       public class Product 
       { 
           [Key] 
           public int Id { get; set; } 
        
           [DataMember] 
           public string Name { get; set; } 
        
           [DataMember] 
           public virtual Category Category { get; set; } 
       }

JsonObject(IsReference = true)] is for JSON.NET and [DataContract(IsReference = true)] is for XmlDCSerializer. Note that: after applying DataContract on class, you need to add DataMember to properties that you want to serialize.

The attributes can be applied on both json and xml serializer and gives more controls on model class.

这篇关于检测到类型的 JSON.NET 错误自引用循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆