You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 21:12:57