如何用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
相关产品推荐
相关产品推荐

