如何在同一列表存储多个派生类?C# JSON反序列化场景
派生类列表存储与反序列化属性访问解决方案
完全可以在List<SubMenuVariant>中存储不同类型的派生类实例,核心是解决反序列化时的类型识别问题,以及后续访问子类专属属性的问题。由于你的列表同一时间只会包含一种子类类型,处理逻辑可以更简化。
1. 解决反序列化的类型识别问题
默认的JsonSerializer反序列化到基类时无法自动识别子类,需要通过自定义JSON转换器来根据JSON中的属性判断具体类型:
自定义JSON转换器实现
public class SubMenuVariantConverter : JsonConverter<SubMenuVariant> { public override SubMenuVariant Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using var doc = JsonDocument.ParseValue(ref reader); var root = doc.RootElement; // 根据JSON中存在的专属属性判断子类类型 if (root.TryGetProperty("SubMenuTitle", out _)) { return JsonSerializer.Deserialize<SubMenuItem>(root.GetRawText(), options); } else if (root.TryGetProperty("HighlightTitle", out _)) { return JsonSerializer.Deserialize<SubMenuHighlightItem>(root.GetRawText(), options); } throw new JsonException("无法识别的SubMenuVariant子类类型"); } public override void Write(Utf8JsonWriter writer, SubMenuVariant value, JsonSerializerOptions options) { // 序列化时根据实例实际类型输出JSON JsonSerializer.Serialize(writer, value, value.GetType(), options); } }
注册转换器并反序列化
var serializerOptions = new JsonSerializerOptions(); serializerOptions.Converters.Add(new SubMenuVariantConverter()); // 假设根类结构如下 public class MenuRoot { public List<SubMenuVariant> submenu { get; set; } } // 执行反序列化 var menuRoot = JsonSerializer.Deserialize<MenuRoot>(jsonString, serializerOptions); var submenu = menuRoot.submenu;
2. 访问子类专属属性
反序列化完成后,列表中的实例已为实际子类类型,可通过以下两种方式访问专属属性:
方式一:批量类型转换(适合列表仅含单一子类的场景)
// 转换为SubMenuItem列表 var subMenuItems = submenu.Cast<SubMenuItem>().ToList(); foreach (var item in subMenuItems) { Console.WriteLine(item.SubMenuTitle); // 访问Link、SubItems等专属属性 } // 转换为SubMenuHighlightItem列表 var highlightItems = submenu.Cast<SubMenuHighlightItem>().ToList(); foreach (var item in highlightItems) { Console.WriteLine(item.HighlightTitle); // 访问HighlightText、HighLightLink等专属属性 }
方式二:模式匹配(更安全,支持混合类型场景)
foreach (var variant in submenu) { if (variant is SubMenuItem menuItem) { Console.WriteLine(menuItem.SubMenuTitle); } else if (variant is SubMenuHighlightItem highlightItem) { Console.WriteLine(highlightItem.HighlightTitle); } }
关键修正提示
你的SubMenuHighlightItem类存在重复的JsonPropertyName特性,会导致序列化/反序列化错误,需修正:
public class SubMenuHighlightItem : SubMenuVariant { [JsonPropertyName(FieldNames.HighlightTitle)] public string HighlightTitle { get; set; } [JsonPropertyName(FieldNames.HighlightText)] public string HighlightText { get; set; } // 修正此处特性名称,匹配Link对应的字段名 [JsonPropertyName(FieldNames.HighlightLink)] public Link HighLightLink { get; set; } }
内容的提问来源于stack exchange,提问作者I am not Fat
相关产品推荐
相关产品推荐

