Newtonsoft.Json 处理多态类型的反序列化
Posted 零点blog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Newtonsoft.Json 处理多态类型的反序列化相关的知识,希望对你有一定的参考价值。
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
以上是关于Newtonsoft.Json 处理多态类型的反序列化的主要内容,如果未能解决你的问题,请参考以下文章
System.Text.Json 中是不是可以进行多态反序列化?
C# dynamic类型序列化和反序列化之Newtonsoft.Json,动态解析远端返回的jSON数据
“Newtonsoft.Json.JsonConvert”类型存在于“Newtonsoft.Json.dll”和“NuGetApi2.dll”中
C# Newtonsoft.Json JsonSerializerSettings 全局序列化设置
无法将类型“newtonsoft.json.linq.jtoken”隐式转换为 newt“newtonsoft.json.linq.jvalue”