(转)Json Self referencing loop
作者:互联网
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
修复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/59078428
Self referencing loop detected......的错误
解决方案:
1 增加 [JsonIgnore] 过滤关联,使其不参与序列化。
这个方法简单粗暴。但是你就没办法获取关联的json对象。
2 序列化时,使用如下代码,list是model对象(只适合关联对象较少)
(但是经过楼主测试,关联比较多,比较复杂时,还是没卵用,直接卡死。这个问题的原因呼之欲出,也是由于主外键对象互相深度循环,牵涉到的实体层较多,关联对象更多,就不赘述了)
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
string result = JsonConvert.SerializeObject(list, settings);
为了引用方便,我们可以作为扩展方法:
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
标签:Category,set,get,Self,Json,referencing,序列化,public,ReferenceLoopHandling 来源: https://www.cnblogs.com/stableboy/p/11066264.html