在 Json.net 中序列化一对多关系
Posted
技术标签:
【中文标题】在 Json.net 中序列化一对多关系【英文标题】:Serialize one to many relationships in Json.net 【发布时间】:2011-08-11 18:28:48 【问题描述】:我首先使用实体框架代码进行数据访问,并且我有一个包含员工集合的公司类。 Employee 类也有一个 Company 属性。
我希望能够对 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 对象时,出现序列化异常“检测到类型的自引用循环”。
谢谢。
【问题讨论】:
JSON.NET Error Self referencing loop detected for type的可能重复 我知道这个问题(稍微)旧一些,但这个问题的答案更好。这也是我要发送所有其他副本的地方。 【参考方案1】:更新答案
您可以:
重新配置 json.net 以忽略 自引用循环 使用 [JsonIgnore] 属性 使用自定义转换器删除 子导航 或者您可以使用数据传输对象【讨论】:
我试过了,它导致了堆栈溢出,即无限循环......另外,你是如何配置它来忽略自引用的。也许您以其他可行的方式做到了... 那你有设计问题。您需要删除一个引用或使用在员工方面只有一个引用的 POCO。我在我的智能手机上,所以我无法检查它。我认为客户上的员工参考不正确。 您能详细说明“设计问题”是什么意思吗?课程超级简单。 Company 有一个 IList我认为他们已经在最新版本中修复了这个问题。
查看“序列化和反序列化 JSON -> 序列化和保留对象引用”部分下的 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”属性。
【讨论】:
就此主题写了一篇博文:johnnycode.com/blog/2012/04/10/… 为我指明了正确的方向。请注意,JsonFormatter 现在已嵌入 WebApi,因此您需要做的就是设置 PreserveReferencesHandling 设置。 你有没有想过我在发布 json 时需要他们的关系,因为一个学生在健身房有很多预订【参考方案3】:如果这对任何人都有帮助,我想我会记录下我们在使用 Entity Framework 4.3.1 和 JSON.Net 4.5.3 时如何解决同样的错误。
我们使用的是 Database First DbContext 方法。根据我们的需要,我们可以使用[JsonIgnore]
属性来解决它。诀窍在于,当您从数据库刷新时,自动生成的实体类的更改会被覆盖,使用 Database First,您可以使用this *** post 中给出的“元数据伙伴类”方法添加属性。
以下是代码摘录。我们有一个与“公司”和“用户”对象有关系的“查询”对象 (class Query
)。在一个新的类文件中,我们用[MetadataType]
属性声明部分类,然后在我们指定的QueryMetadata
类中,我们注释我们想要忽略的成员——即EF4.x 添加到的public virtual
成员表达关系(又名导航属性)。
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;
但是,如果我们实际上还必须序列化相关的 Company 或 User 对象,我们就碰壁了! John Bubriski here 建议的方法对我们不起作用,因为我们想依赖实体框架更改跟踪。
【讨论】:
【参考方案4】:如果您在使用 WebApi 时遇到此错误,您可以在 WebApiConfig.cs 中添加以下内容,以便 json.net 忽略循环引用
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
Microsoft : Loop Reference handling in Web API
【讨论】:
由于某种原因我收到了cannot resolve symbol ReferenceLoopHandling
【参考方案5】:
如果您使用的是 WebAPI EntityFrameworkCore 2.0,此解决方案不起作用,您需要在 Startup.cs->ConfigureServices 上进行设置:
.AddJsonOptions(options =>
var settings = options.SerializerSettings;
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
);
【讨论】:
似乎忽略某些东西是不好的,但我已经在多个地方看到过这种情况。为什么这样做还不错?以上是关于在 Json.net 中序列化一对多关系的主要内容,如果未能解决你的问题,请参考以下文章