System.Text.Json序列化:如何查看转换类型及触发未识别类型异常?
关于System.Text.Json多态转换的两个问题解答
1. 确定当前正在尝试转换的类型
当使用PolymorphismOptions配置多态映射时,默认JsonTypeInfoResolver返回基类型的JsonTypeInfo是正常行为,但你可以通过两种方式获取实际要转换的派生类型:
利用
PolymorphismOptions的鉴别器回调:配置多态选项时,通过OnDiscriminatorResolved回调可直接拿到解析出的目标派生类型。示例:var options = new JsonSerializerOptions { TypeInfoResolver = new DefaultJsonTypeInfoResolver { Modifiers = { typeInfo => { if (typeInfo.Type == typeof(BaseType)) { typeInfo.PolymorphismOptions = new JsonPolymorphismOptions { TypeDiscriminatorPropertyName = "$type", IgnoreUnrecognizedTypeDiscriminators = false, OnDiscriminatorResolved = (discriminatorValue, resolvedType) => { // resolvedType即为当前尝试转换的实际派生类型 Console.WriteLine($"当前转换类型:{resolvedType.FullName}"); }, DerivedTypes = { new JsonDerivedType(typeof(DerivedType1), "Derived1"), new JsonDerivedType(typeof(DerivedType2), "Derived2") } }; } } } } };自定义
JsonConverter捕获实际类型:如果需要更精细的控制,可编写自定义转换器,读取鉴别器值后匹配对应的派生类型:public class BaseTypeConverter : JsonConverter<BaseType> { public override BaseType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using (var doc = JsonDocument.ParseValue(ref reader)) { var root = doc.RootElement; if (root.TryGetProperty("$type", out var discriminatorElem)) { var discriminator = discriminatorElem.GetString(); Type targetType = discriminator switch { "Derived1" => typeof(DerivedType1), "Derived2" => typeof(DerivedType2), _ => throw new JsonException($"未知鉴别器:{discriminator}") }; // targetType就是当前尝试转换的实际类型 return (BaseType)JsonSerializer.Deserialize(root.GetRawText(), targetType, options); } throw new JsonException("缺少类型鉴别器"); } } public override void Write(Utf8JsonWriter writer, BaseType value, JsonSerializerOptions options) { JsonSerializer.Serialize(writer, value, value.GetType(), options); } }
2. 发现问题时抛出异常
System.Text.Json提供多种方式在转换出错时抛出异常:
配置
PolymorphismOptions处理鉴别器不匹配:设置IgnoreUnrecognizedTypeDiscriminators = false,并通过OnDiscriminatorMismatch回调主动抛出异常:typeInfo.PolymorphismOptions = new JsonPolymorphismOptions { TypeDiscriminatorPropertyName = "$type", IgnoreUnrecognizedTypeDiscriminators = false, OnDiscriminatorMismatch = (discriminatorValue, baseType) => { throw new JsonException($"无法将鉴别器'{discriminatorValue}'映射到{baseType.FullName}的任何派生类型"); }, DerivedTypes = { /* 派生类型配置 */ } };设置
JsonSerializerOptions全局异常规则:UnknownTypeHandling = JsonUnknownTypeHandling.ThrowException:遇到无法识别的类型时抛出异常;UnknownPropertyHandling = JsonUnknownPropertyHandling.Throw:JSON中存在目标类型无对应属性时抛出异常;AllowTrailingCommas = false:禁止JSON末尾逗号,否则抛出异常。
示例:
var options = new JsonSerializerOptions { UnknownTypeHandling = JsonUnknownTypeHandling.ThrowException, UnknownPropertyHandling = JsonUnknownPropertyHandling.Throw, AllowTrailingCommas = false };自定义转换器中主动抛出异常:在自定义转换器的
Read方法中,检测到数据不符合预期(如缺少必要属性、类型不匹配)时,直接抛出JsonException,如前面的BaseTypeConverter示例所示。
内容的提问来源于stack exchange,提问作者Locke
相关产品推荐
相关产品推荐

