FastAPI自定义异常处理:优雅转换Pydantic校验错误
FastAPI自定义异常处理:优雅转换Pydantic校验错误
背景需求
当使用FastAPI开发API服务时,Pydantic的自动校验异常默认会返回如下格式的422响应:
{"detail": [{"type": "missing","loc": ["body", "user", "name"],"msg": "Field required","input": null}]
}
但在实际开发中我们通常需要:
- 统一异常响应格式
- 增加自定义错误码
- 对敏感信息进行过滤
- 支持多语言错误提示
实现方案
步骤1:创建自定义异常类
from fastapi import HTTPExceptionclass APIException(HTTPException):def __init__(self,code: int = 40000,message: str = "请求参数错误",status_code: int = 400,**kwargs):super().__init__(status_code=status_code,detail={"code": code,"message": message,"data": kwargs.get("data", None)})
步骤2:捕获Pydantic校验异常
2.1 异常捕获机制原理
2.1.1 FastAPI的异常处理链
# FastAPI的异常处理流程示意图
客户端请求 -> 路由函数 -> 中间件处理 -> 参数校验 -> 业务逻辑 -> 返回响应↑异常捕获点 ↑校验异常触发点异常处理器介入 ←─ 异常抛出
- 捕获时机:当请求参数不符合Pydantic模型定义时,框架会自动抛出
RequestValidationError
(HTTP 422错误) - 处理器注册:通过
@app.exception_handler
装饰器绑定特定异常类型到处理函数
2.1.2 关键异常类型区分
异常类型 | 触发场景 | 继承关系 |
---|---|---|
ValidationError | 手动调用模型验证时抛出 | Pydantic原生异常 |
RequestValidationError | FastAPI自动参数校验失败 | 继承自ValidationError |
2.2 核心处理逻辑剖析
2.2.1 错误数据结构解构
# 原始错误条目结构示例
{"type": "value_error", # 错误大类"loc": ("body", "age"), # 错误位置元组"msg": "输入值不是合法整数", # 原始错误描述"input": "eighteen" # 客户端原始输入
}
字段深度说明:
-
loc
定位器:- 遵循
(位置类型, 字段路径...)
结构 - 位置类型可能为:
body
,query
,path
,header
,cookie
- 嵌套字段示例:
("body", "user", "address", "city")
- 遵循
-
常见错误类型:
# Pydantic预定义错误类型参考 "missing" # 必填字段缺失 "value_error" # 值校验失败 "type_error" # 类型不匹配 "assertion_error" # 自定义校验断言失败
2.2.2 错误信息处理流程
def