json.net;序列化实体框架对象(循环引用错误)

时间:2022-08-23 08:32:45

I have an entity framework entity that i want to serialize as a json object. I looked around and found out that json.net (http://james.newtonking.com/projects/json-net.aspx) should be able to serialize objects with circular references "out of the box". So i tried using

我有一个实体框架实体,我想将其序列化为json对象。我查看了一下,发现json.net (http://james.newtonking.com/projects/json-net.aspx)应该能够将具有循环引用的对象序列化为“跳出框”。所以我试着用

string json = JsonConvert.SerializeObject(/* my ef entity */);

But im still getting the same error. The problem might be that i need to use ReferenceLoopHandling.Ignore and a ContractResolver, but im not sure how to use them. Any help is much appreciated! Thanks

但我还是得到了同样的错误。问题可能是我需要使用ReferenceLoopHandling。忽视和一个合同解决者,但我不确定如何使用它们。非常感谢您的帮助!谢谢

5 个解决方案

#1


2  

My solution was to simply remove the parent reference on my child entities.

我的解决方案是删除子实体上的父引用。

So in my model, I selected the relationship and changed the Parent reference to be Internal rather than Public.

所以在我的模型中,我选择了关系并将父引用改为内部引用而不是公共引用。

May not be an ideal solution for all, but worked for me.

也许对所有人来说都不是一个理想的解决方案,但对我来说很有用。

#2


14  

To get around this I converted my Entities to POCO based Code First. To do this right click inside your edmx window and select:

为了解决这个问题,我首先将我的实体转换为基于POCO的代码。要做到这一点,请在您的edmx窗口中单击并选择:

Add code generation item > Code tab > EF POCO Entity Generator.

添加代码生成项>代码选项卡> POCO实体生成器。

Note that you might need to install it with nuget if you don't see it.

注意,如果没有看到,可能需要使用nuget来安装它。

At runtime however EF adds proxy classes to those objects for tracking purposes but they tend to mess up with the serialization process. To prevent this we can simply set ProxyCreationEnabled to false as follows:

然而,在运行时,EF将代理类添加到这些对象中用于跟踪目的,但它们往往会打乱序列化过程。为了防止这种情况发生,我们可以将ProxyCreationEnabled设置为false,如下所示:

var context = new YourEntities();
context.Configuration.ProxyCreationEnabled = false;

var results = context.YourEntity.Take(100).ToList();

You can then safely return JSON.NET serialized data by omitting the default reference looping as follows:

然后可以安全地返回JSON。NET序列化数据,省略默认引用循环如下:

return JsonConvert.SerializeObject(results, Formatting.Indented, 
    new JsonSerializerSettings { 
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore 
    });

#3


9  

Another solution will be adding [JsonIgnore] attribute to your navigational properties.

另一个解决方案是向导航属性添加[JsonIgnore]属性。

For example:

例如:

using System;
using System.ComponentModel.DataAnnotations.Schema;

[Serializable]
public class Entity
{
    public int EntityID { get; set; }
    public string EntityName { get; set; }

    [JsonIgnore]
    public virtual Parent Parent { get; set; }
    [JsonIgnore]
    public virtual List<Child> Children { get; set; }
}

#4


6  

I used the following solution to clone my entities, no tricks where required regarding data attributes on the entities and my table circular references got preserved. I even had entities pointing to each other witout any problems. Required library for the serializaton is Json.Net (the Newtonsoft.Json dll).

我使用下面的解决方案来克隆我的实体,不需要对实体上的数据属性进行任何操作,我的表循环引用也得到了保留。我甚至有实体指向对方,阻止任何问题的发生。serializaton所需的库是Json。净(Newtonsoft。Json dll)。

    private static T CloneObject<T>(T obj)
    {
        if (obj == null)
            return obj;
        string ser = JsonConvert.SerializeObject(obj, Formatting.Indented, 
            new JsonSerializerSettings() {
                                NullValueHandling = NullValueHandling.Ignore,
                                MissingMemberHandling = MissingMemberHandling.Ignore,
                                ReferenceLoopHandling = ReferenceLoopHandling.Ignore});
        return (T) JsonConvert.DeserializeObject(ser, obj.GetType());
    }

Example usage:

使用示例:

    protected object CopyObj(Object obj)
    {
        return CloneObject(obj);
    }
    var cust1 = this.cts.Customers().Where(cc => cc.Id == 3).Include(cc => cc.Addresses).FirstOrDefault();
    var cust2 = CopyObj(cust1) as Customers;  
    //Cust2 now includes copies of the customer record and its addresses

#5


1  

Try this: First making sure poco or model has DataContract, DataMemeber and remove virtual key word..then..

尝试一下:首先确保poco或模型有DataContract、DataMemeber和删除虚拟关键词。

 public string Get()
    {
        var list = _languageRepository.GetMany(l => l.LanguageTrans.FirstOrDefault().CultureCode == "en").ToList();

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

        return json;
    }

#1


2  

My solution was to simply remove the parent reference on my child entities.

我的解决方案是删除子实体上的父引用。

So in my model, I selected the relationship and changed the Parent reference to be Internal rather than Public.

所以在我的模型中,我选择了关系并将父引用改为内部引用而不是公共引用。

May not be an ideal solution for all, but worked for me.

也许对所有人来说都不是一个理想的解决方案,但对我来说很有用。

#2


14  

To get around this I converted my Entities to POCO based Code First. To do this right click inside your edmx window and select:

为了解决这个问题,我首先将我的实体转换为基于POCO的代码。要做到这一点,请在您的edmx窗口中单击并选择:

Add code generation item > Code tab > EF POCO Entity Generator.

添加代码生成项>代码选项卡> POCO实体生成器。

Note that you might need to install it with nuget if you don't see it.

注意,如果没有看到,可能需要使用nuget来安装它。

At runtime however EF adds proxy classes to those objects for tracking purposes but they tend to mess up with the serialization process. To prevent this we can simply set ProxyCreationEnabled to false as follows:

然而,在运行时,EF将代理类添加到这些对象中用于跟踪目的,但它们往往会打乱序列化过程。为了防止这种情况发生,我们可以将ProxyCreationEnabled设置为false,如下所示:

var context = new YourEntities();
context.Configuration.ProxyCreationEnabled = false;

var results = context.YourEntity.Take(100).ToList();

You can then safely return JSON.NET serialized data by omitting the default reference looping as follows:

然后可以安全地返回JSON。NET序列化数据,省略默认引用循环如下:

return JsonConvert.SerializeObject(results, Formatting.Indented, 
    new JsonSerializerSettings { 
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore 
    });

#3


9  

Another solution will be adding [JsonIgnore] attribute to your navigational properties.

另一个解决方案是向导航属性添加[JsonIgnore]属性。

For example:

例如:

using System;
using System.ComponentModel.DataAnnotations.Schema;

[Serializable]
public class Entity
{
    public int EntityID { get; set; }
    public string EntityName { get; set; }

    [JsonIgnore]
    public virtual Parent Parent { get; set; }
    [JsonIgnore]
    public virtual List<Child> Children { get; set; }
}

#4


6  

I used the following solution to clone my entities, no tricks where required regarding data attributes on the entities and my table circular references got preserved. I even had entities pointing to each other witout any problems. Required library for the serializaton is Json.Net (the Newtonsoft.Json dll).

我使用下面的解决方案来克隆我的实体,不需要对实体上的数据属性进行任何操作,我的表循环引用也得到了保留。我甚至有实体指向对方,阻止任何问题的发生。serializaton所需的库是Json。净(Newtonsoft。Json dll)。

    private static T CloneObject<T>(T obj)
    {
        if (obj == null)
            return obj;
        string ser = JsonConvert.SerializeObject(obj, Formatting.Indented, 
            new JsonSerializerSettings() {
                                NullValueHandling = NullValueHandling.Ignore,
                                MissingMemberHandling = MissingMemberHandling.Ignore,
                                ReferenceLoopHandling = ReferenceLoopHandling.Ignore});
        return (T) JsonConvert.DeserializeObject(ser, obj.GetType());
    }

Example usage:

使用示例:

    protected object CopyObj(Object obj)
    {
        return CloneObject(obj);
    }
    var cust1 = this.cts.Customers().Where(cc => cc.Id == 3).Include(cc => cc.Addresses).FirstOrDefault();
    var cust2 = CopyObj(cust1) as Customers;  
    //Cust2 now includes copies of the customer record and its addresses

#5


1  

Try this: First making sure poco or model has DataContract, DataMemeber and remove virtual key word..then..

尝试一下:首先确保poco或模型有DataContract、DataMemeber和删除虚拟关键词。

 public string Get()
    {
        var list = _languageRepository.GetMany(l => l.LanguageTrans.FirstOrDefault().CultureCode == "en").ToList();

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

        return json;
    }