如何在JSON.NET中使用List <T>属性进行序列化期间将空JSON属性默认为空数组?

Met*_*uru 7 arrays null default list json.net

目前我有JSON,它通过HTTP调用进入或存储在数据库中,但在服务器处理期间,它们被映射到C#对象.

这些对象具有类似的属性public List<int> MyArray.

当JSON包含时,MyArray:null我希望结果属性为空List<T>而不是null List<T>属性.

目标是该对象将"重新序列化"为JSON MyArray:[],因此要么保存到数据库,要么通过HTTP作为空数组而不是null.

这样,无论如何,C#类基本上都是为任何List<T>属性进行清理并强制执行一个空数组,否则会null导致浏览器端代码中断(例如:) cannot read property 'length' of null.

有没有一种方法,在序列化/反序列化过程中,我可以将任何与List<T>属性配对的空值变为空数组?

jti*_*ley 9

如果null为空,你总是可以延迟加载一个空列表.

要么

在JsonDeserializer上使用NullValueHandling选项.

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

return JsonConvert.DeserializeObject<T>(json, settings);
Run Code Online (Sandbox Code Playgroud)

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


Ed'*_*'ka 9

以下属性将在反序列化后为其分配空集合,而不是null在这两种情况下:当在 JSON 中省略该属性或显式设置时null

class A
{
    [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    public IEnumerable<int> Prop { get; set; } = new List<int>();
}
Run Code Online (Sandbox Code Playgroud)


Bri*_*ers 7

我打算建议使用自定义JsonConverter来解决这个问题,但转换器不会被调用null值.相反,您需要将自定义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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个演示如何使用解析器的演示:

class Program
{
    static void Main(string[] args)
    {
        JsonSerializerSettings settings = new JsonSerializerSettings();
        settings.ContractResolver = new NullToEmptyListResolver();
        settings.ObjectCreationHandling = ObjectCreationHandling.Replace;
        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; }
}
Run Code Online (Sandbox Code Playgroud)

输出:

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

Deserializing JSON with null lists...
IntList size: 0
StringList size: 0
Run Code Online (Sandbox Code Playgroud)