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

C# JSON反序列化如何根据PartType值实例化Component对应子类

多态JSON列表反序列化实现方案

这是典型的多态反序列化场景:默认JSON反序列化器只会按照属性声明的基类Component实例化对象,不会自动识别子类类型,需要自定义类型映射规则,根据每个列表项的PartType字段值创建对应子类实例。
以下分别给出.NET生态最常用的两个JSON序列化库的实现方式:

方案一:Newtonsoft.Json (Json.NET)

这是.NET生态使用最广泛的第三方JSON库,通过自定义类型转换器即可实现需求:

  1. 编写多态转换器,读取PartType字段映射对应类型
public class ComponentTypeConverter : JsonConverter<Component>
{
    public override Component ReadJson(JsonReader reader, Type objectType, Component existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        // 加载当前JSON对象,读取类型标识字段
        JObject currentObj = JObject.Load(reader);
        string partType = currentObj["PartType"]?.ToString();
        
        // 根据类型标识创建对应子类实例
        Component instance = partType switch
        {
            nameof(Window) => new Window(),
            nameof(Engine) => new Engine(),
            nameof(Door) => new Door(),
            _ => new Component() // 未知类型回退到基类
        };

        // 自动填充所有匹配字段到实例
        serializer.Populate(currentObj.CreateReader(), instance);
        return instance;
    }

    public override void WriteJson(JsonWriter writer, Component value, JsonSerializer serializer)
    {
        // 无序列化需求可直接抛异常,标记CanWrite为false即可跳过该方法
        throw new NotImplementedException();
    }

    public override bool CanWrite => false;
}
  1. 反序列化时加载转换器
var serializerSettings = new JsonSerializerSettings
{
    Converters = { new ComponentTypeConverter() }
};
Product product = JsonConvert.DeserializeObject<Product>(apiResponseJson, serializerSettings);

如果不想每次反序列化都传入配置,可以直接在Product类的Components属性上标记[JsonConverter(typeof(ComponentTypeConverter))]特性,转换器会自动生效。

方案二:System.Text.Json (.NET 内置JSON库)

根据你使用的.NET版本不同,实现方式略有区别:

.NET 7 及以上版本

框架原生支持多态反序列化配置,不需要写自定义转换器,直接在基类上标记特性即可:

// 指定类型判别字段为PartType
[JsonPolymorphic(TypeDiscriminatorPropertyName = nameof(Component.PartType))]
// 映射每个类型标识对应的子类
[JsonDerivedType(typeof(Window), "Window")]
[JsonDerivedType(typeof(Engine), "Engine")]
[JsonDerivedType(typeof(Door), "Door")]
public class Component
{
    public string PartType { get; set; }
}

配置完成后直接调用默认反序列化方法即可:

Product product = JsonSerializer.Deserialize<Product>(apiResponseJson);

.NET 6 及以下版本

低版本没有内置多态特性,需要自定义转换器实现,逻辑和Newtonsoft.Json类似:

public class ComponentTypeConverter : JsonConverter<Component>
{
    public override Component Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        // 解析当前JSON节点,读取类型标识
        using JsonDocument doc = JsonDocument.ParseValue(ref reader);
        JsonElement root = doc.RootElement;
        string partType = root.GetProperty("PartType").GetString();

        Component instance = partType switch
        {
            nameof(Window) => new Window(),
            nameof(Engine) => new Engine(),
            nameof(Door) => new Door(),
            _ => new Component()
        };

        // 反序列化为对应子类实例
        return (Component)JsonSerializer.Deserialize(root.GetRawText(), instance.GetType(), options);
    }

    public override void Write(Utf8JsonWriter writer, Component value, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }
}

反序列化时将转换器加入配置即可:

var jsonOptions = new JsonSerializerOptions
{
    Converters = { new ComponentTypeConverter() }
};
Product product = JsonSerializer.Deserialize<Product>(apiResponseJson, jsonOptions);

结果验证

反序列化完成后遍历product.Components列表即可看到:

  • PartType值为Window的元素是Window类实例,可直接访问Operation、Tinted属性
  • PartType值为Engine的元素是Engine类实例,可直接访问Capacity、Cylinders、Layout属性
  • PartType值为Door的元素是Door类实例,可直接访问DoorStyle属性

内容的提问来源于stack exchange,提问作者Chris Hammond

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 01:21:34