我尝试序列化从实体数据模型.edmx自动生成的POCO类,当我使用
JsonConvert.SerializeObject
我得到了以下错误:
为System.data.entity类型检测到自我引用循环错误。
我怎么解决这个问题?
我尝试序列化从实体数据模型.edmx自动生成的POCO类,当我使用
JsonConvert.SerializeObject
我得到了以下错误:
为System.data.entity类型检测到自我引用循环错误。
我怎么解决这个问题?
当前回答
最好的解决方案是从Web API中的循环引用处理(这个答案的大部分都是从这里复制的):
修复1:全局忽略循环引用
(我已经选择/尝试了这一个,就像其他许多人一样)
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
如果你想在非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);
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.
其他回答
当你有循环问题时,序列化使用NEWTONSOFTJSON,在我的情况下,我不需要修改全局。野蔷薇或野蔷薇。我只是使用JsonSerializesSettings忽略循环处理。
JsonSerializerSettings jss = new JsonSerializerSettings();
jss.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
var lst = db.shCards.Where(m => m.CardID == id).ToList();
string json = JsonConvert.SerializeObject(lst, jss);
我喜欢从Application_Start()做它的解决方案,在这里的答案
显然,我不能在JavaScript中使用我的函数中的配置访问json对象,因为在DalSoft的答案中返回的对象在对象的(键,val)上都有“\n \r”。
不管怎样,只要能工作就好(因为不同的方法在不同的场景下工作,这取决于所提出的意见和问题),尽管最好采用一种标准的方法,并提供一些良好的文档支持该方法。
我继承了一个数据库应用程序,为web页面提供数据模型。默认情况下,序列化将尝试遍历整个模型树,这里的大多数答案都是如何防止这种情况的良好开端。
一个尚未探索的选项是使用接口来提供帮助。我将从之前的例子中窃取:
public partial class CompanyUser
{
public int Id { get; set; }
public int CompanyId { get; set; }
public int UserId { get; set; }
public virtual Company Company { get; set; }
public virtual User User { get; set; }
}
public interface IgnoreUser
{
[JsonIgnore]
User User { get; set; }
}
public interface IgnoreCompany
{
[JsonIgnore]
User User { get; set; }
}
public partial class CompanyUser : IgnoreUser, IgnoreCompany
{
}
在上述解决方案中,没有Json设置受到损害。将LazyLoadingEnabled和或ProxyCreationEnabled设置为false会影响所有的后端编码,并阻止ORM工具的一些真正好处。LazyLoading/ProxyCreation设置可以在不手动加载的情况下阻止导航属性的加载,这取决于您的应用程序。
这里有一个更好的解决方案,以防止导航属性序列化,它使用标准的json功能: 我怎么能做JSON序列化器忽略导航属性?
请确保在您的方法中使用await和async。如果对象没有正确序列化,就会出现此错误。
最好的解决方案是从Web API中的循环引用处理(这个答案的大部分都是从这里复制的):
修复1:全局忽略循环引用
(我已经选择/尝试了这一个,就像其他许多人一样)
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
如果你想在非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);
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.