You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 05:45:08