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

C#使用JavaScriptSerializer反序列化派生类集合仅得到基类实例如何解决

问题原因

转换失败是因为JavaScriptSerializer默认反序列化逻辑仅会创建你指定的声明类型(也就是List<AutoEvent>里的AutoEvent)的实例,不会主动识别JSON中包含的派生类独有字段,所以反序列化得到的所有元素都是基类实例,自然没有派生类的成员,强转也会抛出运行时异常。

解决方案

方案1:继续使用JavaScriptSerializer(自定义转换器)

通过实现自定义的JavaScriptConverter,手动判断JSON对应的实际派生类类型并创建对应实例。

步骤1:实现自定义转换器

public class AutoEventConverter : JavaScriptConverter
{
    public override IEnumerable<Type> SupportedTypes
    {
        get { return new List<Type> { typeof(AutoEvent) }; }
    }

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        // 通过派生类独有字段判断实际类型
        if (dictionary.ContainsKey("RectArea"))
        {
            return serializer.ConvertToType<MouseClickEvent>(dictionary);
        }
        if (dictionary.ContainsKey("ImgTolerance"))
        {
            return serializer.ConvertToType<ClickImageEvent>(dictionary);
        }
        // 无匹配字段返回基类实例
        return serializer.ConvertToType<AutoEvent>(dictionary);
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        // 序列化逻辑无需修改,返回空字典走默认序列化逻辑即可
        return new Dictionary<string, object>();
    }
}

步骤2:注册转换器后执行序列化/反序列化

在创建JavaScriptSerializer实例后,先注册自定义转换器再执行后续操作:

JavaScriptSerializer ser = new JavaScriptSerializer();
// 注册自定义派生类转换器
ser.RegisterConverters(new List<JavaScriptConverter> { new AutoEventConverter() });
// 原有序列化、反序列化逻辑保持不变即可
string json = ser.Serialize(events);
// ... 读写文件逻辑
events = ser.Deserialize<List<AutoEvent>>(json);

方案2:改用Newtonsoft.Json(更推荐)

Newtonsoft.Json(Json.NET)是.NET生态最常用的JSON处理库,原生支持多态类型序列化/反序列化,无需手动写转换器。

步骤1:安装依赖

在NuGet包管理器中安装Newtonsoft.Json,或执行包管理器命令:
Install-Package Newtonsoft.Json

步骤2:修改序列化/反序列化逻辑

配置TypeNameHandling参数,让Json.NET自动在JSON中存储类型信息,反序列化时自动识别创建对应派生类实例:

// 序列化
string json = JsonConvert.SerializeObject(events, new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Auto
});
// 写文件逻辑不变
File.WriteAllText(path, json);

// 反序列化
json = File.ReadAllText(path);
events = JsonConvert.DeserializeObject<List<AutoEvent>>(json, new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Auto
});

注意:如果JSON来源于不可信环境,使用TypeNameHandling存在类型注入风险,仅在内部可信场景下使用该配置即可。

内容的提问来源于stack exchange,提问作者Nenad Birešev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 01:36:07