FastAPI中使用inspect模块生成签名导致Swagger类型注解冗余的问题
这个问题我之前也碰到过,本质是你在BaseModel里混用了FastAPI的Query参数类型,再加上手动构建签名时没正确处理字段的默认值和类型注解导致的,咱们一步步拆解解决:
为什么会出现冗余注解?
看你的FilterSet类:
class FilterSet(BaseModel): first_name: str last_name: str | None = Query(None)
BaseModel的核心是做数据结构验证,而Query是FastAPI专门标记查询参数的工具类。当你把Query(None)直接赋值给BaseModel字段的默认值时,这个字段的default属性就变成了Query对象,而不是单纯的None。
之后你手动构建Parameter时直接用了field_value.default,FastAPI生成Swagger文档时会把Query对象的信息也解析进去,导致类型注解出现冗余,而不是你预期的string | null。另外first_name因为是通过合并BaseModel字段构建签名,FastAPI也没正确识别它的必填性对应的参数类型,所以显示异常。
怎么实现纯净的string | null注解?
我们需要把BaseModel的数据结构定义和FastAPI的参数验证逻辑分开,再在构建签名时正确处理参数默认值:
步骤1:修正BaseModel定义
先把Query从BaseModel里移除,让它只负责数据结构:
class FilterSet(BaseModel): first_name: str # 必填字段 last_name: str | None = None # 可选字段,默认None class Ordering(BaseModel): ordering: str | None = None class Pagination(BaseModel): limit: int offset: int
步骤2:在签名构建时添加Query验证
修改ListService函数,根据字段必填性手动给参数加上Query验证器,这样FastAPI就能正确识别参数类型,生成干净的Swagger注解:
def ListService(service_cls): # 合并三个类的字段 fields = {} fields.update(service_cls.ordering_cls.__fields__) fields.update(service_cls.filterset_cls.__fields__) fields.update(service_cls.pagination_cls.__fields__) parameters = [] for field_name, field_value in fields.items(): # 根据字段是否必填,设置对应的Query默认值 if field_value.required: # 必填字段用Query(...)标记,确保Swagger显示为必填 param_default = Query(...) else: # 可选字段传递原默认值给Query param_default = Query(field_value.default) parameter = Parameter( field_name, Parameter.KEYWORD_ONLY, annotation=field_value.annotation, default=param_default, ) parameters.append(parameter) service_cls.__signature__ = inspect.Signature(parameters) return service_cls
回答你的两个问题
这是正常现象吗?
不是正常现象,这是混用BaseModel和FastAPI参数类型,加上手动签名构建处理不当导致的代码写法问题,不是FastAPI的默认行为。能不能只显示
string | null?
完全可以!按上面的方法修改后,Swagger里的last_name会显示为string | null,first_name显示为必填的string,和你预期的一致。
内容来源于stack exchange

