How to make Json.Net skip serialization of empty collections

前端 未结 2 957
攒了一身酷
攒了一身酷 2020-12-06 10:47

I have an object that contains several properties that are a List of strings List or a dictionary of strings Dictionary

相关标签:
2条回答
  • 2020-12-06 11:42

    Another very simple solution is to implement a ShouldSerialize* method in the type being serialized as outline here.

    This might be the preferred way if you're in control of the type being serialized and if it is not a general behavior you want to introduce.

    0 讨论(0)
  • 2020-12-06 11:44

    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.

    0 讨论(0)
提交回复
热议问题