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

Ema*_*mad 19 serialization entity-framework json.net ef-code-first

我首先使用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; }
}
Run Code Online (Sandbox Code Playgroud)

这是员工

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; }
}
Run Code Online (Sandbox Code Playgroud)

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

谢谢.

Joh*_*ski 14

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

查看" 序列化和反序列化JSON - >序列化和保留对象引用 " 部分下的帮助文档.

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

PreserveReferencesHandling = PreserveReferencesHandling.Objects;
Run Code Online (Sandbox Code Playgroud)

所以一个例子是这样的:

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

string json = JsonConvert.SerializeObject(people, Formatting.Indented, serializerSettings);
Run Code Online (Sandbox Code Playgroud)

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


sra*_*sra 6

更新的答案

你可以:

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


Mar*_*ATS 5

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

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

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

Query实体也有外键的字段(命名FK_User,并FK_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; }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我们实际上还必须序列化相关的公司或用户对象,我们就会碰壁砖墙!通过建议的做法约翰Bubriski 这里,因为我们要依靠实体框架更改跟踪不会为我们工作.


Jus*_*ore 5

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

config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; 
Run Code Online (Sandbox Code Playgroud)

Microsoft:Web API中的循环引用处理