我使用Newtonsoft JSON序列化在附属程序集中定义的对象图。我有一个循环引用,它导致JSON中的递归限制被超过,并给已经数据量很大的POST添加了额外的膨胀。
有文档记录的方法是将JsonIgnore
属性添加到我的数据对象的属性中,但这需要在我的域项目中使用Newtonsoft.Json引用。是否有其他方法将属性从序列化中排除?
备选方案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;
您可以在引用System.Runtime.Serialization
的模型属性上应用[IgnoreDataMember]
属性。默认情况下,所有其他属性都将被序列化。
例如
public class MyViewModel
{
public string SerializedProperty { get; set; }
[IgnoreDataMember]
public string IgnoredProperty { get; set; }
}
也有类似的问题。在序列化时,我用一个自定义属性和契约解析器以一种完全过度编写和过度设计的方式解决了它,所以我不需要在模型中引用任何外部libs(System除外)。
声明您自己的属性,例如
[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 });