在C#中如何反序列化包含不同派生类的列表?
解决方法
要实现这个需求,你需要自定义一个JsonConverter,让Json.NET能根据JSON对象里的字段判断应该实例化哪个派生类。具体步骤如下:
1. 自定义JSON转换器
创建一个继承自JsonConverter的类,在ReadJson方法里根据JSON对象的属性区分Adult和Child:
public class HumanConverter : JsonConverter { public override bool CanConvert(Type objectType) { // 只处理BaseHumanClass及其派生类 return typeof(BaseHumanClass).IsAssignableFrom(objectType); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // 把JSON对象加载成JObject,方便判断属性 var jObject = JObject.Load(reader); // 存在Name字段则实例化Adult if (jObject.ContainsKey("Name")) { var adult = new Adult(); serializer.Populate(jObject.CreateReader(), adult); return adult; } // 存在Age字段则实例化Child else if (jObject.ContainsKey("Age")) { var child = new Child(); serializer.Populate(jObject.CreateReader(), child); return child; } // 无匹配字段时返回基类实例(也可根据需求抛出异常) else { var baseHuman = new BaseHumanClass(); serializer.Populate(jObject.CreateReader(), baseHuman); return baseHuman; } } // 若无需序列化,WriteJson可留空或抛出异常 public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException("自定义转换器仅用于反序列化"); } }
2. 使用转换器反序列化
调用JsonConvert.DeserializeObject时传入自定义转换器即可:
string json = "[{ \"Id\": 1, \"Name\": \"Dave\" }, { \"Id\": 2, \"Age\": 64 }]"; // 反序列化成包含对应派生类实例的列表 var humanList = JsonConvert.DeserializeObject<List<BaseHumanClass>>(json, new HumanConverter()); // 验证结果示例 foreach (var human in humanList) { if (human is Adult adult) Console.WriteLine($"成人:ID={adult.Id},姓名={adult.Name}"); else if (human is Child child) Console.WriteLine($"儿童:ID={child.Id},年龄={child.Age}"); }
关键点说明
CanConvert方法限定转换器的处理范围,避免不必要的类型干扰。- 通过
JObject.ContainsKey识别JSON对象的特征字段,以此确定实例化的派生类类型。 serializer.Populate可以自动完成属性赋值,无需手动逐个映射字段,简化代码。
内容的提问来源于stack exchange,提问作者mudale
相关产品推荐
相关产品推荐

