我在反序列化 Json 多态时遇到问题。这是一个最小的例子:
我有一个定义 JSON 类型的枚举:
public enum BlockType
{
T1,
T2
}
基类和子类(以及容器):
public class Container
{
required public List<BaseType> ListOfItems { get; set; }
}
[JsonPolymorphic(TypeDiscriminatorPropertyName = nameof(Type))]
[JsonDerivedType(typeof(Type2), nameof(BlockType.T1))]
[JsonDerivedType(typeof(Type2), nameof(BlockType.T2))]
public class BaseType
{
[JsonConverter(typeof(JsonStringEnumConverter))]
required public BlockType Type { get; set; }
}
public class Type1 : BaseType
{
required public int Value1 { get; set; }
}
public class Type2 : BaseType
{
required public int Value2 { get; set; }
}
我有一个输入 JSON:
var jsonBody = """
{
"ListOfItems": [
{
"type": "T1",
"Value1": 10
},
{
"type": "T2",
"Value2": 11
}
]
}
""";
并调用序列化器:
var deserializeOptions = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
WriteIndented = true,
};
var decoded = JsonSerializer.Deserialize<Container>(jsonBody, deserializeOptions);
序列化器不会返回任何错误。但是,当我检查返回的类型和列表
Container.ListOfItems
时,其中的每个项目都是BaseType
,而不是派生的Type1
或Type2
。事实上,如果我投射该物体:
foreach (BaseType o in decoded.ListOfItems)
{
if (o.Type == BlockType.T1)
{
Type1 obj = (Type1)o;
}
}
我会得到一个
InvalidCastException: Cannot convert BaseType to Type1.
这个问题有解决办法吗?
我个人已经放弃使用[JsonPolymorphic],而是编写了一个转换器。上述类的转换器看起来像这样
public class BaseTypeConverter : JsonConverter<BaseType>
{
public override BaseType? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using var doc = JsonDocument.ParseValue(ref reader);
var typestr = doc.RootElement.GetProperty("type").GetString()?.ToUpper();
if (Enum.TryParse(typestr, out BlockType type)) {
if (type == BlockType.T1) {
return JsonSerializer.Deserialize<Type1>(doc.RootElement.GetRawText(), options);
}
else
{
return JsonSerializer.Deserialize<Type2>(doc.RootElement.GetRawText(), options);
}
}
}
public override void Write(Utf8JsonWriter writer, BaseType value, JsonSerializerOptions options)
{
// I'm only interested in deserializing
throw new NotImplementedException();
}
}