在Json.net中序列化一对多关系

时间:2011-04-24 07:07:00

标签: entity-framework serialization ef-code-first json.net

我首先使用Entity Framework代码进行数据访问,并且我有一个具有Employees集合的Company类。 Employee类还有一个Company属性。

我希望能够序列化公司并在序列化中包含员工列表。

这是公司:

public class Company
{
public long Id { get; set; }
public string Name { get; set; }
public DateTime? Established { get; set; }

public virtual IList<Employee> Employees { get; set; }

public DateTime? DateCreated { get; set; }
public DateTime? DateUpdated { get; set; }
}

这是员工

public class Employee
{
public long Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }

public virtual Company Company { get; set; }

public DateTime? DateCreated { get; set; }
public DateTime? DateUpdated { get; set; }
}

当我尝试序列化Company对象时,我得到序列化异常“检测到类型的自引用循环”。

感谢。

5 个答案:

答案 0 :(得分:14)

我认为他们已经在最新版本中解决了这个问题。

查看“序列化和反序列化JSON - &gt;序列化和保留对象引用”部分下的help docs

初始化JSON.Net Serializer时设置此设置:

PreserveReferencesHandling = PreserveReferencesHandling.Objects;

一个例子是:

var serializerSettings = new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects };

string json = JsonConvert.SerializeObject(people, Formatting.Indented, serializerSettings);

我确认这适用于我的代码第一个解决方案,以及导航属性中的循环引用。如果你看看生成的JSON,它应该在任何地方都有“$ id”和“$ ref”属性。

答案 1 :(得分:6)

更新的答案

你可以:

  • 重新配置json.net以忽略 自引用循环
  • 使用[JsonIgnore]属性
  • 使用删除的自定义转换器 孩子的导航
  • 或者您可以使用数据传输对象

答案 2 :(得分:5)

如果这有助于任何人,我想我会记录在使用Entity Framework 4.3.1和JSON.Net 4.5.3时我们如何为我们的目的解决同样的错误。

我们正在使用Database First DbContext方法。根据我们的需求,我们可以使用[JsonIgnore]属性解决此问题。诀窍在于,当您从数据库刷新时会覆盖对自动生成的实体类的更改,使用Database First,您可以使用this StackOverflow post中给出的“元数据伙伴类”方法添加属性。

以下是代码摘录。我们有一个“查询”对象(class Query)与“公司”和“用户”对象有关系。在新的类文件中,我们使用[MetadataType]属性声明部分类,然后在我们指定的QueryMetadata类中,我们注释要忽略的成员 - 即public virtual成员EF4.x添加表达关系(又名导航属性)。

Query实体还有外键字段(在我们的例子中名为FK_UserFK_Company)。这些字段不需要[JsonIgnore]属性 - 它们可以使用其外键值序列化。

[MetadataType(typeof(QueryMetadata))]
public partial class Query
{
}


public class QueryMetadata
{
    [JsonIgnore]
    public virtual Company company { get; set; }
    [JsonIgnore]
    public virtual User user { get; set; }
}

但是,如果我们真的不得不序列化相关的公司或用户对象,我们就会碰壁砖墙! John Bubriski here建议的方法对我们不起作用,因为我们希望依赖实体框架更改跟踪。

答案 3 :(得分:5)

如果您使用WebApi收到此错误,可以将以下内容放在WebApiConfig.cs中,以便json.net忽略循环引用

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

Microsoft : Loop Reference handling in Web API

答案 4 :(得分:1)

如果你正在使用WebAPI EntityFrameworkCore 2.0,这个解决方案不起作用,你需要在Startup.cs-&gt; ConfigureServices上设置它:

.AddJsonOptions(options => {
                    var settings = options.SerializerSettings;
                    settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                });