全局配置 Pydantic 处理 UUID 序列化方案
如果你想在 FastAPI 应用中全局处理 UUID 序列化问题,而不需要为每个模型单独配置,有以下几种全局解决方案:
方案1:自定义 FastAPI JSON 编码器(推荐)
from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from uuid import UUID
import json
app = FastAPI()
# 自定义 JSON 编码器
def custom_json_encoder(obj):
if isinstance(obj, UUID):
return str(obj)
raise TypeError(f"Object of type {obj.__class__.__name__} is not JSON serializable")
# 覆盖默认的 jsonable_encoder 行为
jsonable_encoder.ENCODERS_BY_TYPE[UUID] = lambda x: str(x)
# 或者更彻底的覆盖(如果需要处理更多类型)
app.json_encoder = json.JSONEncoder(default=custom_json_encoder)
方案2:修改 Pydantic 基础配置(影响所有模型)
from pydantic import BaseConfig
# 全局修改 Pydantic 的 JSON 编码器
BaseConfig.json_encoders = {
UUID: lambda v: str(v),
}
# 注意:这会影响应用中所有 Pydantic 模型
方案3:创建自定义基础模型
from pydantic import BaseModel
from uuid import UUID
class CustomBaseModel(BaseModel):
class Config:
json_encoders = {
UUID: lambda v: str(v),
}
# 然后让所有模型继承这个基础模型
SomeModelPydantic = pydantic_model_creator(
SomeModel,
name="SomeModelPydantic",
base=CustomBaseModel # 使用自定义基础模型
)
方案4:猴子补丁 Tortoise 的 pydantic_model_creator
from tortoise.contrib.pydantic import pydantic_model_creator
from pydantic import BaseConfig
original_creator = pydantic_model_creator
def patched_pydantic_model_creator(*args, **kwargs):
model = original_creator(*args, **kwargs)
if not hasattr(model.Config, 'json_encoders'):
model.Config.json_encoders = {}
model.Config.json_encoders[UUID] = lambda v: str(v)
return model
# 应用猴子补丁
pydantic_model_creator = patched_pydantic_model_creator
推荐方案
推荐使用方案1,因为它:
- 是 FastAPI 官方推荐的方式
- 不会影响 Pydantic 的其他行为
- 作用范围明确,只影响 FastAPI 的 JSON 响应
- 可以轻松扩展以处理其他自定义类型的序列化
注意事项
- 这些全局修改应该在应用启动时尽早执行
- 如果使用了异步 ORM(如 Tortoise-ORM),确保在 ORM 初始化之前完成这些配置
- 全局修改可能会影响应用中其他部分的预期行为,建议在测试环境中充分验证