FastAPI接口枚举验证异常:字符串参数无法匹配枚举成员
问题描述
我定义了如下自定义枚举类:
class CustomEnum(Enum): ONE = 1 TWO = 2
并编写了FastAPI接口:
@router.post(...) async def example(request: Request, param: CustomEnum = Body(...)): print(param.value) # 应返回整数
当请求负载为:
{ "param": "ONE" }
时,触发错误:Bad data - param: value is not a valid enumeration member; permitted: 1, 2
我需要前后端通过字符串通信,但后端要快速将"ONE"映射为1,本以为枚举是最佳方案,请问哪里操作有误?
问题原因与解决办法
问题出在默认情况下,FastAPI会把枚举的值(value)作为校验和序列化的依据,而不是枚举的名称(name)。你传的是枚举名称"ONE",但FastAPI期望接收的是枚举对应的值1或2,所以报错。
下面是两种实用的解决方式:
方式一:用StrEnum(Python 3.11+)
如果你的Python版本是3.11及以上,直接改用StrEnum就省事了——它默认会把枚举名称作为序列化/反序列化的依据,同时能保留数值映射:
from enum import StrEnum class CustomEnum(StrEnum): ONE = "ONE" TWO = "TWO" # 加个属性快速转成整数 @property def num_value(self): return 1 if self == self.ONE else 2 # 接口里直接用 @router.post(...) async def example(request: Request, param: CustomEnum = Body(...)): print(param.num_value) # 输出1或2
要是想把枚举值直接设为字符串类型的数字,也可以这么写:
class CustomEnum(StrEnum): ONE = "1" TWO = "2" @router.post(...) async def example(request: Request, param: CustomEnum = Body(...)): print(int(param.value)) # 输出1或2
方式二:自定义参数解析逻辑(兼容低版本Python)
如果Python版本低于3.11,给FastAPI加个校验函数,把传入的字符串名称转成对应的枚举成员就行:
from enum import Enum from pydantic import BeforeValidator class CustomEnum(Enum): ONE = 1 TWO = 2 # 写个简单的转换函数 def str_to_custom_enum(v): if isinstance(v, str): return CustomEnum[v] # 通过名称获取枚举成员 return v # 接口里用Body的validator参数指定这个函数 @router.post(...) async def example( request: Request, param: CustomEnum = Body(..., pre=True, validator=BeforeValidator(str_to_custom_enum)) ): print(param.value) # 输出1或2
也可以把这个逻辑放到Pydantic模型里,这样多个接口都能复用:
from pydantic import BaseModel, BeforeValidator class RequestBody(BaseModel): param: CustomEnum = Field(..., validator=BeforeValidator(str_to_custom_enum)) @router.post(...) async def example(request: Request, body: RequestBody): print(body.param.value) # 输出1或2
内容的提问来源于stack exchange,提问作者KevP
相关产品推荐
相关产品推荐

