How is the default null JSON property for an empty array during serialization with the List <T> property in JSON.NET?

Currently, I have JSON that either comes through an HTTP call or is stored in a database, but during server processing, they are mapped to C # objects.

These objects have properties such as public List<int> MyArray.

When JSON contains MyArray:null, I want the resulting property to be empty List<T>instead of the null property List<T>.

The goal is that the object will be “re-serialized” to JSON as MyArray:[], thus, either save to the database or respond via HTTP as an empty array instead null.

Thus, regardless of the fact that the C # class basically cleans up and uses an empty array for any property List<T>that would otherwise nulllead to things breaking in the browser code (for example:) cannot read property 'length' of null.

Is there a way that during serialization / deserialization, I can have any NULL value that is associated with a property List<T>, instead becomes empty?

+7
source share
4 answers

You can always be lazy to load an empty list if its value is zero.

OR

Use the NullValueHandling parameter in the JsonDeserializer.

var settings = new JsonSerializerSettings();
settings.NullValueHandling = NullValueHandling.Ignore;

return JsonConvert.DeserializeObject<T>(json, settings);

http://james.newtonking.com/json/help/index.html?topic=html/SerializationSettings.htm

+9

JsonConverter , . IContractResolver IValueProvider. , ( ):

class NullToEmptyListResolver : DefaultContractResolver
{
    protected override IValueProvider CreateMemberValueProvider(MemberInfo member)
    {
        IValueProvider provider = base.CreateMemberValueProvider(member);

        if (member.MemberType == MemberTypes.Property)
        {
            Type propType = ((PropertyInfo)member).PropertyType;
            if (propType.IsGenericType && 
                propType.GetGenericTypeDefinition() == typeof(List<>))
            {
                return new EmptyListValueProvider(provider, propType);
            }
        }

        return provider;
    }

    class EmptyListValueProvider : IValueProvider
    {
        private IValueProvider innerProvider;
        private object defaultValue;

        public EmptyListValueProvider(IValueProvider innerProvider, Type listType)
        {
            this.innerProvider = innerProvider;
            defaultValue = Activator.CreateInstance(listType);
        }

        public void SetValue(object target, object value)
        {
            innerProvider.SetValue(target, value ?? defaultValue);
        }

        public object GetValue(object target)
        {
            return innerProvider.GetValue(target) ?? defaultValue;
        }
    }
}

, :

class Program
{
    static void Main(string[] args)
    {
        JsonSerializerSettings settings = new JsonSerializerSettings();
        settings.ContractResolver = new NullToEmptyListResolver();
        settings.Formatting = Formatting.Indented;

        Console.WriteLine("Serializing object with null lists...");
        Foo foo = new Foo();
        string json = JsonConvert.SerializeObject(foo, settings);
        Console.WriteLine(json);
        Console.WriteLine();

        Console.WriteLine("Deserializing JSON with null lists...");
        json = @"{ ""IntList"" : null, ""StringList"" : null }";
        foo = JsonConvert.DeserializeObject<Foo>(json, settings);
        Console.WriteLine("IntList size: " + foo.IntList.Count);
        Console.WriteLine("StringList size: " + foo.StringList.Count);
    }
}

class Foo
{
    public List<int> IntList { get; set; }
    public List<string> StringList { get; set; }
}

:

Serializing object with null lists...
{
  "IntList": [],
  "StringList": []
}

Deserializing JSON with null lists...
IntList size: 0
StringList size: 0
+6

.net, IsGenericType, Type TypeInfo.

, ( NullValueHandling), , , null.

.net:

using System;
using System.Collections.Generic;
using Newtonsoft.Json.Serialization;
using System.Reflection;

public class NullToEmptyListResolver : DefaultContractResolver
{
    protected override IValueProvider CreateMemberValueProvider(MemberInfo member)
    {
        IValueProvider provider = base.CreateMemberValueProvider(member);

        if (member.MemberType == MemberTypes.Property)
        {
            Type propType = ((PropertyInfo)member).PropertyType;
            TypeInfo propTypeInfo = propType.GetTypeInfo();
            if (propTypeInfo.IsGenericType &&
                propType.GetGenericTypeDefinition() == typeof(List<>))
            {
                return new EmptyListValueProvider(provider, propType);
            }
        }

        return provider;
    }

    class EmptyListValueProvider : IValueProvider
    {
        private IValueProvider innerProvider;
        private object defaultValue;

        public EmptyListValueProvider(IValueProvider innerProvider, Type listType)
        {
            this.innerProvider = innerProvider;
            defaultValue = Activator.CreateInstance(listType);
        }

        public void SetValue(object target, object value)
        {
            innerProvider.SetValue(target, value ?? defaultValue);
        }

        public object GetValue(object target)
        {
            return innerProvider.GetValue(target) ?? defaultValue;
        }
    }
}
+2
source

The following property will have an empty collection assigned to it after deserialization, instead nullin both cases: when the property is skipped in JSON or when the value is explicitly set null:

class A
{
    [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    public IEnumerable<int> Prop { get; set; } = new List<int>();
}
0
source

All Articles