JSON 序列化程序如何忽略导航属性?
Posted
技术标签:
【中文标题】JSON 序列化程序如何忽略导航属性?【英文标题】:How can I do JSON serializer ignore navigation properties? 【发布时间】:2019-08-02 16:34:48 【问题描述】:我和这个问题完全一样: How do I make JSON.NET ignore object relationships?
我看到了建议的解决方案,我知道我必须使用 Contract Revolver,我也看到了 Contract Resolver 的代码,但我不知道如何使用它。
我应该在 WebApiConfig.vb 中使用它吗? 我还是应该修改我的实体模型吗?【问题讨论】:
如果你和我的情况一样,这里是我的建议:忘记它,将你的控制器更改为 OData。完美运行,JSON序列化器没有问题。 卡洛斯,我的波纹管解决方案有效,您可以将其标记为正确答案吗? 我已经标记了你的答案,RAM,因为它有一些支持,所以它必须工作。但我对此发表评论是因为它可能很有用(如果对我来说)。在构造函数中,Configuration.LazyLoadingEnabled 成功了: public ExampleController() db.Configuration.LazyLoadingEnabled = false; 谢谢。我的答案也适用于True
和False
属性的LazyLoadingEnabled
值。
【参考方案1】:
这是一个有用的问题?希望对您有所帮助:
A)
如果您手动创建了模型(没有Entity Framework
),首先将关系属性标记为virtual
。
如果您的模型是由EF
创建的,它已经为您完成了,每个Relation Property
都标记为virtual
,如下所示:
Sample class:
public class PC
public int FileFolderId get;set;
public virtual ICollection<string> Libs get; set;
public virtual ICollection<string> Books get; set;
public virtual ICollection<string> Files get; set;
B)
JSON
序列化程序现在可以忽略这些关系属性,方法是使用以下 ContractResolver
for JSON.NET
:
CustomResolver:
class CustomResolver : DefaultContractResolver
private readonly List<string> _namesOfVirtualPropsToKeep=new List<string>(new String[]);
public CustomResolver()
public CustomResolver(IEnumerable<string> namesOfVirtualPropsToKeep)
this._namesOfVirtualPropsToKeep = namesOfVirtualPropsToKeep.Select(x=>x.ToLower()).ToList();
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
JsonProperty prop = base.CreateProperty(member, memberSerialization);
var propInfo = member as PropertyInfo;
if (propInfo != null)
if (propInfo.GetMethod.IsVirtual && !propInfo.GetMethod.IsFinal
&& !_namesOfVirtualPropsToKeep.Contains(propInfo.Name.ToLower()))
prop.ShouldSerialize = obj => false;
return prop;
C)
最后,使用上面的ContractResolver
轻松序列化您的模型。像这样设置它:
// -------------------------------------------------------------------
// Serializer settings
JsonSerializerSettings settings = new JsonSerializerSettings
// ContractResolver = new CustomResolver();
// OR:
ContractResolver = new CustomResolver(new []
nameof(PC.Libs), // keep Libs property among virtual properties
nameof(PC.Files) // keep Files property among virtual properties
),
PreserveReferencesHandling = PreserveReferencesHandling.None,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
Formatting = Formatting.Indented
;
// -------------------------------------------------------------------
// Do the serialization and output to the console
var json = JsonConvert.SerializeObject(new PC(), settings);
Console.WriteLine(json);
// -------------------------------------------------------------------
// We can see that "Books" filed is ignored in the output:
//
// "FileFolderId": 0,
// "Libs": null,
// "Files": null
//
现在,所有导航(关系)属性 [virtual
属性] 将被自动忽略,除非您通过在代码中确定它们来保留其中一些。?
Live DEMO
感谢@BrianRogers 的回答here。
【讨论】:
你是个救命恩人!! 这是一个很好的答案。 @RAM,您是否知道有条件地仅包含特定虚拟集合的方法,可以通过自定义注释或其他方式? @Janne,我更新了我的答案以支持保留某些属性的名称(尽管我们也可以基于属性制定解决方案)。我还添加了一个 Live Demo 的链接。 ? 感谢分享@RAM,我会在以后的计划中考虑到这一点。 ... 只是一个快速通知@RAM,*** 上的代码示例是部分的,因为它缺少对 _namesOfVirtualPropsToKeep 的处理(只是 IF 语句的一个条件),但 Live DEMO 包含这个缺失的壮举。只是想让你知道。感谢您的解决方案!【参考方案2】:如果您使用的是Newtonsoft.Json
用
标记字段Newtonsoft.Json.JsonIgnore
而不是
System.Text.Json.Serialization.JsonIgnore
【讨论】:
以上是关于JSON 序列化程序如何忽略导航属性?的主要内容,如果未能解决你的问题,请参考以下文章
如何让 Json.Net 在不忽略子属性的情况下从 documentDB 序列化/反序列化动态/通用对象?
有没有一种方法可以使JavaScriptSerializer忽略某些通用类型的属性?
在使用 Jackson 反序列化期间选择性地忽略 JSON 属性