问题描述
我尝试序列化从 Entity Data Model .edmx 和我使用时自动生成的 POCO 类
I tried to serialize POCO class that was automatically generated from Entity Data Model .edmx and when I used
JsonConvert.SerializeObject
我收到以下错误:
检测到类型 System.data.entity 的错误自引用循环发生.
Error Self referencing loop detected for type System.data.entity occurs.
我该如何解决这个问题?
How do I solve this problem?
推荐答案
这是最好的解决方案https://docs.microsoft.com/en-us/archive/blogs/hongyes/loop-reference-handling-in-web-api
(我已经选择/尝试过这个,和其他许多人一样)
json.net 序列化程序有一个忽略循环引用的选项.将以下代码放入 WebApiConfig.cs
文件中:
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:
- 数据丢失循环引用信息
- 修复仅适用于 JSON.net
- 如果有很深的引用链,则无法控制引用的级别
如果你想在非 api 的 ASP.NET 项目中使用这个修复,你可以在 Global.asax.cs
中添加上述行,但首先添加:
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;
如果你想在 .Net Core 项目中使用它,你可以将 Startup.cs
更改为:
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);
修复 2:全局保留循环引用
第二个修复与第一个类似.只需将代码更改为:
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"
}
]
$id 和 $ref 保留所有引用并使对象图级别平坦,但客户端代码需要知道形状更改才能使用数据,并且它也仅适用于 JSON.NET 序列化程序.
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.
此修复是在模型类上装饰属性以控制模型或属性级别的序列化行为.要忽略该属性:
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 用于 JSON.NET,IgnoreDataMember 用于 XmlDCSerializer.保留参考:
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)]
用于 JSON.NET,[DataContract(IsReference = true)]
用于 XmlDCSerializer.注意:在类上应用DataContract
后,需要将DataMember
添加到要序列化的属性中.
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.
这些属性可以应用在 json 和 xml 序列化器上,并提供对模型类的更多控制.
The attributes can be applied on both json and xml serializer and gives more controls on model class.
这篇关于JSON.NET 错误检测到类型的自引用循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!