我有一个对象,其中包含多个属性,这些属性是字符串列表List<String>
或字符串字典Dictionary<string,string>
。我想使用Json.net将对象序列化为json,我希望生成最少量的文本。
我使用DefaultValueHandling和NullValueHandling将默认值设置为字符串和整数。但是,如果将DefaultValueHandling初始化为空List<String>
或Dictionary<string,string>
,我如何定义DefaultValueHandling以忽略序列化输出中的属性?
一些示例输出是:
{
"Value1": "my value",
"Value2": 3,
"List1": [],
"List2": []
}
我想得到一个忽略上例中两个列表的结果,因为它们被设置为空列表的默认值。
任何帮助将不胜感激
答案 0 :(得分:15)
我已在我个人框架的custom contract resolver中实现了此功能(如果稍后会移动文件,请链接到specific commit)。它使用一些辅助方法,并包含一些不相关的自定义引用语法代码。没有它们,代码将是:
public class SkipEmptyContractResolver : DefaultContractResolver
{
public SkipEmptyContractResolver (bool shareCache = false) : base(shareCache) { }
protected override JsonProperty CreateProperty (MemberInfo member,
MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
bool isDefaultValueIgnored =
((property.DefaultValueHandling ?? DefaultValueHandling.Ignore)
& DefaultValueHandling.Ignore) != 0;
if (isDefaultValueIgnored
&& !typeof(string).IsAssignableFrom(property.PropertyType)
&& typeof(IEnumerable).IsAssignableFrom(property.PropertyType)) {
Predicate<object> newShouldSerialize = obj => {
var collection = property.ValueProvider.GetValue(obj) as ICollection;
return collection == null || collection.Count != 0;
};
Predicate<object> oldShouldSerialize = property.ShouldSerialize;
property.ShouldSerialize = oldShouldSerialize != null
? o => oldShouldSerialize(o) && newShouldSerialize(o)
: newShouldSerialize;
}
return property;
}
}
除非为属性或字段指定ICollection
,否则此合约解析程序将跳过所有空集合(所有类型实现Length == 0
并具有DefaultValueHandling.Include
)的序列化。
答案 1 :(得分:8)
另一个非常简单的解决方案是在被序列化为大纲here的类型中实现ShouldSerialize*
方法。
如果你控制了被序列化的类型,并且它不是你想要引入的一般行为,那么这可能是首选方法。