Solución:
Siempre puede cargar de forma diferida una lista vacía si es nula.
O
Utilice la opción NullValueHandling en 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
Iba a sugerir el uso de un personalizado JsonConverter
para resolver esto, pero no se llamará a un convertidor para valores nulos. En su lugar, necesitará utilizar un IContractResolver
en combinación con una costumbre IValueProvider
. Aquí está el código que necesitaría (inspirado en esta respuesta):
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;
}
}
}
Aquí hay una demostración que muestra cómo usar el resolutor:
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; }
}
Producción:
Serializing object with null lists...
{
"IntList": [],
"StringList": []
}
Deserializing JSON with null lists...
IntList size: 0
StringList size: 0
La siguiente propiedad tendrá una colección vacía asignada después de la deserialización en lugar de null
en ambos casos: cuando la propiedad se omite en JSON o cuando se establece en null
explícitamente:
class A
{
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public IEnumerable<int> Prop { get; set; } = new List<int>();
}