如何使Json.Net跳过空集合的序列化

时间:2013-08-27 17:25:47

标签: c# asp.net serialization json.net

我有一个对象,其中包含多个属性,这些属性是字符串列表List<String>或字符串字典Dictionary<string,string>。我想使用Json.net将对象序列化为json,我希望生成最少量的文本。

我使用DefaultValueHandling和NullValueHandling将默认值设置为字符串和整数。但是,如果将DefaultValueHandling初始化为空List<String>Dictionary<string,string>,我如何定义DefaultValueHandling以忽略序列化输出中的属性?

一些示例输出是:

{
 "Value1": "my value",
 "Value2": 3,
 "List1": [],
 "List2": []
}

我想得到一个忽略上例中两个列表的结果,因为它们被设置为空列表的默认值。

任何帮助将不胜感激

2 个答案:

答案 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*方法。

如果你控制了被序列化的类型,并且它不是你想要引入的一般行为,那么这可能是首选方法。