如何使用Newtonsoft JSON.NET将JSON反序列化为IEnumerable <BaseType>

给这个JSON:

[ { "$id": "1", "$type": "MyAssembly.ClassA, MyAssembly", "Email": "me@here.com", }, { "$id": "2", "$type": "MyAssembly.ClassB, MyAssembly", "Email": "me@here.com", } ] 

和这些类:

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

我如何反序列化JSON到:

 IEnumerable<BaseClass> deserialized; 

我不能使用JsonConvert.Deserialize<IEnumerable<BaseClass>>()因为它抱怨BaseClass是抽象的。

你需要:

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

所以JSON看起来像这样:

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

那么你可以反序列化它:

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

文档: TypeNameHandling设置

反序列化时使用下面的JsonSerializerSettings构造:

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

这是一个不需要在json中填充$ type的方法。

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(); } } 

使用它:

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

从这里采取

你也可以将这个枚举包装在一个类中:

 class Wrapper { IEnumerable<BaseClass> classes; } 

然后序列化和反序列化这个。