Newtonsoft.Json的序列化和反序列化很成熟也很好用, 最近在處理多態類型的反序列化中遇到了問題, 反序列化后只能到基類,而得不到也不能轉換到子類。從網上查詢了一番后,需要寫一個創建類型的Converter, 下面我們一步一步來:
1. 首先說明類型的定義, 為了做這個實驗,我定義了一個基類和兩個子類, 然后我要序列化的對象包含了這個基類的集合。
namespace LexSry { using Newtonsoft.Json; using System.Collections.Generic; class DemoData { [JsonProperty("demoId")] public int DemoId { get; set; } [JsonProperty("demos")] public List<DemoBase> Demos { get; set; } } public class DemoBase { [JsonProperty("id")] public int Id { get; set; } [JsonProperty("name")] public string Name { get; set; } [JsonProperty("type")] public string Type { get; set; } } public class DemoA : DemoBase { [JsonProperty("color")] public string Color { get; set; } } public class DemoB: DemoBase { [JsonProperty("size")] public double[] Size { get; set; } } }
2. 序列化,反序列化方法。反序列化時使用 JsonConvert.DeserializeObject<T>(string value, param JsonConverter[] converter)。 通過自己定義JsonConverter來實現創建相應的子類。
在本演示中, 我首先創建了抽象類 JsonCreationConverter<T>:JsonConverter ,
其次, 針對於DemoBase的解析, 我創建了 JsonDemoConverter:JsonCreationConverter<DemoBase>
class JsonParser3 { public static void WriteJson(object t, string file) { JsonSerializer serializer = new JsonSerializer(); using (StreamWriter sw = new StreamWriter(file)) { using (JsonWriter writer = new JsonTextWriter(sw)) { serializer.Serialize(writer, t); } } } public static void ReadJson<T>(string file, out T obj) { JsonSerializer serializer = new JsonSerializer(); using (StreamReader sr = new StreamReader(file)) { obj = JsonConvert.DeserializeObject<T>(sr.ReadToEnd(),new JsonDemoConverter()); } } } public abstract class JsonCreationConverter<T>:JsonConverter { protected abstract T Create(Type objectType, JObject jsonObject); public override bool CanConvert(Type objectType) { return typeof(T).IsAssignableFrom(objectType); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var jsonObject = JObject.Load(reader); var target = Create(objectType, jsonObject); serializer.Populate(jsonObject.CreateReader(), target); return target; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } } public class JsonDemoConverter:JsonCreationConverter<DemoBase> { protected override DemoBase Create(Type objectType, JObject jsonObject) { var typeName = jsonObject["type"].ToString(); switch(typeName) { case "A": return new DemoA(); case "B": return new DemoB(); default: return null; } } } }
3. 在代碼中實現將內存中的對象序列化到test.json中, 然后,從test.json中將數據反序列化到內存對象nData:
DemoData data = new DemoData() { DemoId = 1, Demos = new List<DemoBase>() { new DemoA() {Id=1, Name="demoA", Type="A",Color="red" }, new DemoB() {Id=2, Name="", Type="B",Size= new double[]{ 10,10} } } }; JsonParser3.WriteJson(data, "test.json"); DemoData nData = new DemoData(); JsonParser3.ReadJson<DemoData>("test.json", out nData);
4. test.json中的數據:
{ "demoId": 1, "demos": [ { "color": "red", "id": 1, "name": "demoA", "type": "A" }, { "size": [ 10.0, 10.0 ], "id": 2, "name": "", "type": "B" } ] }
5. 反序列化后, 內存中得到的對象nData