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

.NET 7中F#自定义JsonConverter失效问题求助

问题:.NET 7升级后F#自定义JsonConverter失效

项目从.NET 5/6升级到.NET 7后,原本正常工作的F#自定义JsonConverter突然失效,返回DTO时抛出F#判别式联合序列化不支持的异常。


自定义JsonConverter代码

type RouteCheckConverter() =
    inherit JsonConverter<RouteCheckResponse>()

    override _.Read(reader, _, _): RouteCheckResponse =
        match reader.GetInt32() with 
        | 200 -> RouteOk
        | 301 -> RouteRedirect
        | 404 -> RouteNotFound
        | _ -> failwithf "Unknown route check response"

    override _.Write (writer, r, _): unit =
        match r with
        | RouteOk -> writer.WriteNumberValue 200
        | RouteRedirect -> writer.WriteNumberValue 301
        | RouteNotFound -> writer.WriteNumberValue 404

判别式联合定义

type RouteCheckResponse = | RouteOk | RouteRedirect | RouteNotFound

使用转换器的DTO类

type RouteCheckResultDTO = {
    page: ProductPageDTO option
    redirectTo: string option
    [<JsonConverter(typeof<RouteCheckConverter>)>] 
    response: RouteCheckResponse
}

抛出的异常信息

Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
System.NotSupportedException: F# discriminated union serialization is not supported. Consider authoring a custom converter for the type.
at System.Text.Json.Serialization.Converters.FSharpTypeConverterFactory.CreateConverter(Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.Serialization.JsonConverterFactory.GetConverterInternal(Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver.GetConverterForType(Type typeToConvert, JsonSerializerOptions options, Boolean resolveJsonConverterAttribute)
at System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver.CreateJsonTypeInfo(Type type, JsonSerializerOptions options)
at System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver.GetTypeInfo(Type type, JsonSerializerOptions options)
at System.Text.Json.JsonSerializerOptions.GetTypeInfoNoCaching(Type type)
at System.Collections.Concurrent.ConcurrentDictionary2.GetOrAdd(TKey key, Func2 valueFactory)
at System.Text.Json.JsonSerializerOptions.GetTypeInfoInternal(Type type, Boolean ensureConfigured, Boolean resolveIfMutable)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo.Configure()
at System.Text.Json.Serialization.Metadata.JsonTypeInfo.InitializePropertyCache()
at System.Text.Json.Serialization.Metadata.JsonTypeInfo.Configure()
at System.Text.Json.Serialization.Metadata.JsonTypeInfo.g__ConfigureLocked|143_0()
--- End of stack trace from previous location ---


原因与解决方案

这不是.NET 7的Bug,而是.NET 7中System.Text.Json新增了FSharpTypeConverterFactory,它会优先处理F#判别式联合类型,导致DTO属性上的JsonConverter注解被忽略。

有两种可行的解决方法:

  • 全局注册自定义转换器:在配置JsonSerializerOptions时,将自定义转换器添加到Converters集合,覆盖默认的F#转换器工厂处理逻辑:
    builder.Services.AddControllers()
        .AddJsonOptions(options =>
        {
            options.JsonSerializerOptions.Converters.Add(RouteCheckConverter())
        })
    
  • 为判别式联合类型直接添加注解:将JsonConverter注解移至判别式联合定义上,而非DTO的属性上:
    [<JsonConverter(typeof<RouteCheckConverter>)>]
    type RouteCheckResponse = | RouteOk | RouteRedirect | RouteNotFound
    

两种方法均可让自定义转换器正常生效,推荐第二种,更贴合类型本身的序列化规则。

内容的提问来源于stack exchange,提问作者eastwing

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 02:01:39