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

如何用System.Text.Json序列化继承List<T>且带额外属性的类型

解决System.Text.Json序列化继承自List的类时额外属性丢失的问题

问题根源

当类直接继承自List<T>(实现了IEnumerable接口),System.Text.Json会默认将其视为集合类型处理,仅序列化集合中的元素,忽略类中额外定义的属性(比如你的TrayName)。多态序列化配置无法解决该问题,因为核心逻辑是序列化器对集合类型的特殊处理,而非多态识别问题。

解决方案

方案1:自定义JsonConverter(保留原有类继承结构)

通过自定义转换器,手动控制序列化/反序列化逻辑,同时保留集合元素和额外属性:

public class MachineTrayConverter : JsonConverter<MachineTray>
{
    public override MachineTray Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        using JsonDocument doc = JsonDocument.ParseValue(ref reader);
        var tray = new MachineTray();
        
        // 读取TrayName属性
        if (doc.RootElement.TryGetProperty("TrayName", out JsonElement nameElem))
        {
            tray.TrayName = nameElem.GetString();
        }
        
        // 读取集合元素
        if (doc.RootElement.TryGetProperty("Coils", out JsonElement coilsElem))
        {
            var coils = JsonSerializer.Deserialize<List<MachineCoil>>(coilsElem.GetRawText(), options);
            tray.AddRange(coils ?? Enumerable.Empty<MachineCoil>());
        }
        
        return tray;
    }

    public override void Write(Utf8JsonWriter writer, MachineTray value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();
        // 序列化TrayName
        writer.WriteString("TrayName", value.TrayName);
        // 序列化集合元素到Coils属性
        writer.WritePropertyName("Coils");
        JsonSerializer.Serialize(writer, value.AsEnumerable(), options);
        writer.WriteEndObject();
    }
}

使用时在序列化配置中添加该转换器:

JsonSerializerOptions JSO = new JsonSerializerOptions
{
    WriteIndented = true
};
JSO.Converters.Add(new MachineTrayConverter());

string JSON = Encoding.UTF8.GetString(JsonSerializer.SerializeToUtf8Bytes(Machines, JSO));

方案2:改用组合模式(推荐,优化类设计)

放弃继承List<T>,改用内部包含集合的组合方式,这更符合面向对象设计原则,也能让序列化器默认正确处理所有属性:

整理后的类结构:

public class MachineTray
{
    public string TrayName { get; set; }
    public List<MachineCoil> Coils { get; set; } = new List<MachineCoil>();

    public MachineTray() { }
}

public class Machine
{
    public List<MachineTray> Trays { get; set; } = new List<MachineTray>();
}

此时无需额外配置,直接使用原有序列化代码即可,序列化结果会包含TrayName和Coils属性。

内容的提问来源于stack exchange,提问作者Martin McNally

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 13:16:03