Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
868 views
in Technique[技术] by (71.8m points)

c# - How to make Json.Net skip serialization of empty collections

I have an object that contains several properties that are a List of strings List<String> or a dictionary of strings Dictionary<string,string>. I want to serialize the object to json using Json.net and I want to have the least amount of text generated.

I am using the DefaultValueHandling and NullValueHandling to set default values to strings and integers. But how can I define the DefaultValueHandling to ignore the property in the serialized output if it is initialized to an empty List<String> or Dictionary<string,string>?

Some sample output is:

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

I want to get a result that ignores the two lists in the above example, because they are set to the default value of an empty list.

Any help will be appreciated

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I have implemented this feature in the custom contract resolver of my personal framework (link to the specific commit in case the file will be moved later). It uses some helper methods and includes some unrelated code for custom references syntax. Without them, the code will be:

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;
    }
}

This contract resolver will skip serialization of all empty collections (all types implementing ICollection and having Length == 0), unless DefaultValueHandling.Include is specified for the property or the field.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...