含枚举的抽象类无法正确序列化,如何用System.Text.Json解决?
解决System.Text.Json序列化卡牌Value字段为空对象的问题
问题出在Card类的Value字段声明为Enum基类型,System.Text.Json默认无法识别具体的枚举派生类型,导致序列化时仅输出空对象{},反序列化也无法正确还原枚举值。以下是仅使用System.Text.Json的解决方案:
方案1:自定义Enum基类转换器
通过实现JsonConverter<Enum>,在序列化时记录枚举的具体类型和值,反序列化时根据记录的类型还原枚举实例。
步骤1:创建自定义转换器
在Domain项目中添加如下转换器类:
using System.Text.Json; using System.Text.Json.Serialization; namespace Domain; public class EnumBaseConverter : JsonConverter<Enum> { public override Enum? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.StartObject) throw new JsonException("枚举值序列化格式错误,应为对象类型"); string? enumTypeFullName = null; string? enumValueStr = null; while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) break; if (reader.TokenType != JsonTokenType.PropertyName) throw new JsonException("枚举值对象格式错误,应包含属性名"); var propName = reader.GetString(); reader.Read(); switch (propName) { case "$type": enumTypeFullName = reader.GetString(); break; case "value": enumValueStr = reader.GetString(); break; default: reader.Skip(); break; } } if (string.IsNullOrEmpty(enumTypeFullName) || string.IsNullOrEmpty(enumValueStr)) throw new JsonException("枚举值缺少类型或值信息"); var enumType = Type.GetType(enumTypeFullName); if (enumType == null || !enumType.IsEnum) throw new JsonException("无效的枚举类型"); return Enum.Parse(enumType, enumValueStr) as Enum; } public override void Write(Utf8JsonWriter writer, Enum value, JsonSerializerOptions options) { writer.WriteStartObject(); writer.WriteString("$type", value.GetType().AssemblyQualifiedName); writer.WriteString("value", value.ToString()); writer.WriteEndObject(); } }
步骤2:为Value字段添加转换器标记
修改Card类的Value字段,指定使用上述转换器:
[JsonDerivedType(typeof(BlackCard), typeDiscriminator: "blackCard")] [JsonDerivedType(typeof(ColoredCard), typeDiscriminator: "coloredCard")] public abstract class Card { [JsonConverter(typeof(EnumBaseConverter))] public Enum Value { get; set; } = default!; }
步骤3:验证序列化与反序列化
现在GameState实例序列化后,卡牌的Value字段会输出类似以下格式的内容:
{ "$type": "Domain.EBlackCardValue, Domain", "value": "Wild" }
反序列化时也能正确还原对应的枚举值。
方案2:调整Card类为泛型结构(可选)
如果允许修改现有类结构,可以将Card改为泛型类,让Value字段直接对应具体枚举类型,避免基类型序列化问题:
[JsonDerivedType(typeof(BlackCard), typeDiscriminator: "blackCard")] [JsonDerivedType(typeof(ColoredCard), typeDiscriminator: "coloredCard")] public abstract class Card<TEnum> where TEnum : Enum { public TEnum Value { get; set; } = default!; } public class BlackCard : Card<EBlackCardValue> { public BlackCard(EBlackCardValue value) { Value = value; } } public class ColoredCard : Card<EColoredCardValue> { public ColoredCard(EColoredCardValue value) { Value = value; } }
这种方式无需自定义转换器,System.Text.Json能直接正确序列化和反序列化枚举值。
内容的提问来源于stack exchange,提问作者Karl Kadak
相关产品推荐
相关产品推荐

