FastAPI中使用Pydantic响应模型如何返回大写格式UUID
FastAPI/Pydantic返回大写UUID标准实现方案
问题背景
在FastAPI中使用Pydantic模型作为响应模型时,框架默认序列化返回的UUID为全小写格式,期望获得非侵入式的标准实现,返回大写形式的UUID,避免使用修改原生类的hack方案。
初始复现代码
from fastapi import FastAPI from pydantic import BaseModel from uuid import UUID, uuid4 app = FastAPI() class Test(BaseModel): ID: UUID @app.get("/test", response_model=Test) async def test(): id_ = uuid4() return Test(ID=id_)
默认返回效果
发起请求后得到的响应中UUID为全小写:
import requests resp = requests.get("http://localhost:8000/test").text # resp值示例:'{"ID":"fffc0b5b-8e8d-4d06-b910-2ae8d616166c"}'
不推荐的hack方案
现有侵入式方案通过猴子补丁修改原生uuid.UUID类的__str__方法实现大写输出,会影响整个Python进程内所有UUID的字符串转换逻辑,可能导致第三方依赖出现非预期行为,不建议生产使用:
# 不推荐 def newstr(self): hex = '%032x' % self.int return ('%s-%s-%s-%s-%s' % (hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:])).upper() uuid.UUID.__str__ = newstr
官方支持的标准实现
FastAPI的响应序列化逻辑由Pydantic实现,可直接通过Pydantic提供的序列化扩展能力实现需求,无需修改原生类。
- 单字段自定义序列化(轻量场景推荐)
针对需要返回大写UUID的单个字段,使用Pydantic内置的字段序列化器单独处理即可,作用范围仅限当前模型的指定字段,无副作用:from fastapi import FastAPI from pydantic import BaseModel, field_serializer from uuid import UUID, uuid4 app = FastAPI() class Test(BaseModel): ID: UUID # 为ID字段指定序列化逻辑 @field_serializer('ID') def serialize_id_to_upper(self, value: UUID) -> str: return str(value).upper() @app.get("/test", response_model=Test) async def test(): return Test(ID=uuid4()) - 全局复用自定义UUID类型(多场景推荐)
如果项目中所有接口的UUID都需要返回大写格式,可自定义一个兼容原生UUID行为的新类型,配置好序列化规则后全局复用,一次定义全项目生效:from uuid import UUID, uuid4 from pydantic import BaseModel, GetCoreSchemaHandler from pydantic_core import core_schema from fastapi import FastAPI class UpperCaseUUID(UUID): @classmethod def __get_pydantic_core_schema__(cls, source_type, handler: GetCoreSchemaHandler): # 保留原生UUID的校验逻辑,仅修改序列化输出 return core_schema.no_info_plain_validator_function( cls._validate, serialization=core_schema.plain_serializer_function_ser_schema( lambda val: str(val).upper(), return_schema=core_schema.str_schema() ) ) @classmethod def _validate(cls, value): if isinstance(value, UUID): return value return cls(value) app = FastAPI() class Test(BaseModel): # 直接使用自定义类型即可自动输出大写UUID ID: UpperCaseUUID @app.get("/test", response_model=Test) async def test(): return Test(ID=uuid4())
注:FastAPI本身未提供修改UUID序列化格式的专属配置项,上述两种方案均为Pydantic官方文档明确支持的扩展方式,兼容OpenAPI文档自动生成、请求参数校验等原生能力。
内容的提问来源于stack exchange,提问作者Ziur Olpa
相关产品推荐
相关产品推荐

