c# json.net

c# - cómo deserializar JSON en IEnumerable<BaseType> con Newtonsoft JSON.NET



(4)

dado este JSON:

[ { "$id": "1", "$type": "MyAssembly.ClassA, MyAssembly", "Email": "[email protected]", }, { "$id": "2", "$type": "MyAssembly.ClassB, MyAssembly", "Email": "[email protected]", } ]

y estas clases:

public abstract class BaseClass { public string Email; } public class ClassA : BaseClass { } public class ClassB : BaseClass { }

¿Cómo puedo deserializar el JSON en:

IEnumerable<BaseClass> deserialized;

No puedo usar JsonConvert.Deserialize<IEnumerable<BaseClass>>() porque se queja de que BaseClass es abstracto.


Aquí hay una manera de hacerlo sin poblar $ type en el json.

Un convertidor Json:

public class FooConverter : JsonConverter { public override bool CanConvert(Type objectType) { return (objectType == typeof(BaseFoo)); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JObject jo = JObject.Load(reader); if (jo["FooBarBuzz"].Value<string>() == "A") return jo.ToObject<AFoo>(serializer); if (jo["FooBarBuzz"].Value<string>() == "B") return jo.ToObject<BFoo>(serializer); return null; } public override bool CanWrite { get { return false; } } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } }

usándolo:

var test = JsonConvert.DeserializeObject<List<BaseFoo>>(result, new JsonSerializerSettings() { Converters = { new FooConverter() } });

tomado de here


También puede ajustar el enumerable en una clase:

class Wrapper { IEnumerable<BaseClass> classes; }

luego serializar y deserializar esto.


necesitas:

JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; string strJson = JsonConvert.SerializeObject(instance, settings);

entonces el JSON se ve así:

{ "$type": "System.Collections.Generic.List`1[[MyAssembly.BaseClass, MyAssembly]], mscorlib", "$values": [ { "$id": "1", "$type": "MyAssembly.ClassA, MyAssembly", "Email": "[email protected]", }, { "$id": "2", "$type": "MyAssembly.ClassB, MyAssembly", "Email": "[email protected]", } ] }

entonces puedes deserializarlo:

BaseClass obj = JsonConvert.DeserializeObject<BaseClass>(strJson, settings)

Documentación: configuración de TypeNameHandling


utilice la siguiente construcción JsonSerializerSettings mientras deserializa:

new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.Objects })