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

.NET7 WebApi JSON反序列化异常消息本地化及处理方案咨询

解决方案

一、捕获反序列化异常并返回固定JSON格式

这类JSON反序列化异常发生在模型绑定之前,ConfigureApiBehaviorOptions无法覆盖这个阶段的错误处理,需要通过自定义异常处理器来捕获并返回固定格式响应。

  1. 实现IExceptionHandler接口处理异常:
using Microsoft.AspNetCore.Diagnostics;
using System.Text.Json;

public class JsonDeserializationExceptionHandler : IExceptionHandler
{
    private readonly ILogger<JsonDeserializationExceptionHandler> _logger;

    public JsonDeserializationExceptionHandler(ILogger<JsonDeserializationExceptionHandler> logger)
    {
        _logger = logger;
    }

    public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken)
    {
        // 匹配JSON反序列化相关异常
        if (exception is JsonException || 
            exception.Message.Contains("JSON", StringComparison.OrdinalIgnoreCase))
        {
            _logger.LogError(exception, "JSON反序列化失败");

            // 构造固定格式响应体
            var errorResponse = new
            {
                Status = StatusCodes.Status400BadRequest,
                Code = "INVALID_JSON",
                Message = "请求体格式错误,请提供有效的JSON内容",
                Timestamp = DateTime.UtcNow
            };

            httpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
            httpContext.Response.ContentType = "application/json";

            await httpContext.Response.WriteAsync(JsonSerializer.Serialize(errorResponse), cancellationToken);
            return true; // 标记异常已处理
        }

        return false; // 其他异常交给后续管道处理
    }
}
  1. 在Program.cs中注册并启用异常处理器:
builder.Services.AddExceptionHandler<JsonDeserializationExceptionHandler>();
builder.Services.AddProblemDetails(); // 可选,用于兜底的问题详情处理

// 中间件顺序:放在UseRouting之后,UseEndpoints之前
app.UseExceptionHandler();

二、实现反序列化异常消息本地化

结合IStringLocalizer实现多语言消息替换,步骤如下:

  1. 创建本地化资源文件
    在项目中添加Resources文件夹,创建资源文件(如ErrorMessages.resx、ErrorMessages.zh-CN.resx),添加对应键值对:
  • BadRequestTitle: 请求格式错误
  • InvalidJsonMsg: 请求体不是有效的JSON格式,请检查后重试
  • EmptyBodyMsg: 请求体内容为空,请提供有效的JSON数据
  1. 修改异常处理器注入本地化服务:
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.Extensions.Localization;
using System.Text.Json;

public class LocalizedJsonDeserializationHandler : IExceptionHandler
{
    private readonly ILogger<LocalizedJsonDeserializationHandler> _logger;
    private readonly IStringLocalizer<ErrorMessages> _localizer;

    public LocalizedJsonDeserializationHandler(
        ILogger<LocalizedJsonDeserializationHandler> logger,
        IStringLocalizer<ErrorMessages> localizer)
    {
        _logger = logger;
        _localizer = localizer;
    }

    public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken)
    {
        if (exception is JsonException jsonEx)
        {
            _logger.LogError(jsonEx, "JSON反序列化失败");

            string detailMsg;
            // 区分空请求体和无效JSON的情况
            if (httpContext.Request.ContentLength == 0 || jsonEx.Message.Contains("empty", StringComparison.OrdinalIgnoreCase))
            {
                detailMsg = _localizer["EmptyBodyMsg"];
            }
            else
            {
                detailMsg = _localizer["InvalidJsonMsg"];
            }

            var localizedResponse = new
            {
                Status = StatusCodes.Status400BadRequest,
                Title = _localizer["BadRequestTitle"],
                Detail = detailMsg,
                Timestamp = DateTime.UtcNow
            };

            httpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
            httpContext.Response.ContentType = "application/json";

            await httpContext.Response.WriteAsync(JsonSerializer.Serialize(localizedResponse), cancellationToken);
            return true;
        }

        return false;
    }
}
  1. 配置本地化服务和中间件:
// 注册本地化服务
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");

builder.Services.AddControllers()
    .AddDataAnnotationsLocalization() // 保留已有的DataAnnotations本地化配置
    .AddJsonOptions(options =>
    {
        // 可根据需求配置JSON序列化选项
    });

// 注册本地化异常处理器
builder.Services.AddExceptionHandler<LocalizedJsonDeserializationHandler>();
builder.Services.AddProblemDetails();

// 配置请求本地化中间件(需放在UseExceptionHandler之前)
var supportedCultures = new[] { "zh-CN", "en-US" };
var localizationOptions = new RequestLocalizationOptions()
    .SetDefaultCulture(supportedCultures[0])
    .AddSupportedCultures(supportedCultures)
    .AddSupportedUICultures(supportedCultures);

app.UseRequestLocalization(localizationOptions);
app.UseExceptionHandler();

关键说明

  • ConfigureApiBehaviorOptions仅处理模型绑定完成后的验证错误,无法覆盖反序列化阶段的异常,因此必须通过IExceptionHandler拦截。
  • 可以通过检查请求体长度或JsonException的具体消息,精准区分“空请求体”和“无效JSON”两种场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 11:01:34