【问题标题】:Excluding properties on domain model objects from JSON从 JSON 中排除域模型对象的属性
【发布时间】:2023-03-03 13:53:02
【问题描述】:
我正在使用 Newtonsoft JSON 序列化在附属程序集中定义的对象图。我有一个循环引用,它导致超出 JSON 中的递归限制,并为已经数据繁重的 POST 添加额外的膨胀。
记录的方法是在我的数据对象的属性中添加 JsonIgnore 属性,但这需要在我的域项目中引用 Newtonsoft.Json。有没有其他方法可以从序列化中排除属性?
【问题讨论】:
标签:
c#
json
asp.net-mvc
serialization
json.net
【解决方案1】:
备选方案 1
您应该可以将[DataContract] 与[DataMember] 一起使用。
[DataContract]
public class MyDomainModel
{
[DataMember]
public string PublicString { get; set; }
public string HiddenString { get; set; }
public MyDomainModel InfiniteReference { get; set; }
}
它需要引用System.Runtime.Serialization。
例子:
[HttpGet]
public MyDomainModel GetModels()
{
var model = new MyDomainModel
{
HiddenString = "Hidden",
PublicString = "Public",
};
model.InfiniteReference = model;
return model;
}
输出:
{
"publicString": "Public"
}
备选方案 2
我有一个循环引用 [...]
您可以使用ReferenceLoopHandling,它只是切断循环引用。但这可能不是您想要的,当您提到其他额外的臃肿时。
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
【解决方案2】:
您可以在模型属性上应用[IgnoreDataMember] 属性,该属性引用System.Runtime.Serialization。默认情况下,所有其他属性都将被序列化。
例如
public class MyViewModel
{
public string SerializedProperty { get; set; }
[IgnoreDataMember]
public string IgnoredProperty { get; set; }
}
【解决方案3】:
有类似的问题。在序列化时,我使用自定义属性和合同解析器以完全过度设计和过度设计的方式解决了它,因此我不需要在我的模型中引用任何外部库(系统除外)。
声明自己的属性,比如
[AttributeUsage(AttributeTargets.Property)]
public sealed class IgnoreMeAttribute : Attribute
{
}
装饰你的模型
[IgnoreMe]
public string IgnoreMePlease { get; set; }
添加一个
public class ShouldSerializeContractResolver : DefaultContractResolver
{
public static readonly ShouldSerializeContractResolver Instance = new ShouldSerializeContractResolver();
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (property.AttributeProvider.GetAttributes(typeof (IgnoreMeAttribute), false).Any())
property.ShouldSerialize = instance => false;
return property;
}
}
并使用它
var result = JsonConvert.SerializeObject(value, Formatting.None, new JsonSerializerSettings { ContractResolver = ShouldSerializeContractResolver.Instance });