使用Json.NET进行序列化时如何省略空集合

时间:2016-01-20 14:47:25

标签: c# json json.net

我使用Newtonsoft的Json.NET 7.0.0.0将类从C#序列化为JSON:

class Foo
{
    public string X;
    public List<string> Y = new List<string>();
}

var json =
    JsonConvert.SerializeObject(
        new Foo(),
        Formatting.Indented,
        new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });

此处json的值为

{ "Y": [] }

但如果{ }是空列表,我希望它为Y

我无法找到满意的方法来实现这一目标。也许有自定义合同解析器?

2 个答案:

答案 0 :(得分:14)

如果您正在寻找可以在不同类型中使用的解决方案,并且不需要任何修改(属性等),那么我认为最好的解决方案是自定义DefaultContractResolver类。它将使用反射来确定给定类型的任何IEnumerable是否为空。

public class IgnoreEmptyEnumerablesResolver : DefaultContractResolver
{
    public new static readonly IgnoreEmptyEnumerablesResolver Instance = new IgnoreEmptyEnumerablesResolver();

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);

        if (property.PropertyType != typeof(string) &&
            typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
        {
            property.ShouldSerialize = instance =>
            {
                IEnumerable enumerable = null;

                // this value could be in a public field or public property
                switch (member.MemberType)
                {
                    case MemberTypes.Property:
                        enumerable = instance
                            .GetType()
                            .GetProperty(member.Name)
                            .GetValue(instance, null) as IEnumerable;
                        break;
                    case MemberTypes.Field:
                        enumerable = instance
                            .GetType()
                            .GetField(member.Name)
                            .GetValue(instance) as IEnumerable;
                        break;
                    default:
                        break;

                }

                if (enumerable != null)
                {
                    // check to see if there is at least one item in the Enumerable
                    return enumerable.GetEnumerator().MoveNext();
                }
                else
                {
                    // if the list is null, we defer the decision to NullValueHandling
                    return true;
                }

            };
        }

        return property;
    }
}

答案 1 :(得分:0)

如果您可以修改类,可以添加Shrink方法并为所有空集合设置null。它需要更改类,但它具有更好的性能。只是另一种选择。