简体   繁体   English

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

[英]How to omit empty collections when serializing with Json.NET

I'm using Newtonsoft's Json.NET 7.0.0.0 to serialize classes to JSON from C#: 我正在使用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 });

The value of json here is 这里json的价值是

{ "Y": [] }

but I would like it to be { } if Y is an empty list. 但如果Y是一个空列表,我希望它是{ }

I couldn't find a satisfactory way to achieve this. 我找不到一个令人满意的方法来实现这一目标。 Maybe with a custom contract resolver? 也许有自定义合约解析?

If you're looking for a solution which can be used generically across different types and does not require any modification (attributes, etc), then the best solution that I can think if would be a custom DefaultContractResolver class. 如果您正在寻找一种可以在不同类型中使用的解决方案,并且不需要任何修改(属性等),那么我认为最好的解决方案是自定义DefaultContractResolver类。 It would use reflection to determine if any IEnumerable s for a given type are empty. 它将使用反射来确定给定类型的任何IEnumerable是否为空。

public class IgnoreEmptyEnumerablesResolver : DefaultContractResolver
{
    public 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;
    }
}

If you can modify your classes, you could add Shrink method and set null for all empty collections. 如果您可以修改类,则可以添加Shrink方法并为所有空集合设置null。 It requires to change the class but it has better performance. 它需要更改类,但它具有更好的性能。 Just another option for you. 只是另一种选择。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM