如何使用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; }
然后序列化和反序列化这个。