Pydantic Model调用.dict()时如何将UUID字段转为字符串存入MongoDB
Pydantic模型向MongoDB存储时UUID自动序列化方案
你遇到的TypeError是因为model.json()返回的是JSON字符串,而MongoDB的写入接口要求传入字典类结构,所以不能直接用这个方法。
你当前手写to_dict()的方案可以解决单个模型的问题,但如果项目中有多个带UUID字段的模型,重复写逻辑会比较冗余,推荐以下更通用的方案:
方案1:使用内置jsonable_encoder(最省事,无需改动模型)
Pydantic(以及FastAPI内置)提供的jsonable_encoder会自动把所有非Python原生类型(包括UUID、datetime、枚举等)转换为可序列化的原生类型,输出结果直接是符合要求的字典:
# Pydantic V1 导入方式 from pydantic import jsonable_encoder # 如果用FastAPI也可以直接从fastapi.encoders导入 # from fastapi.encoders import jsonable_encoder record = TestModel() # 直接传入编码器处理后的结果即可 collection.insert_one(jsonable_encoder(record))
方案2:封装通用BaseModel基类(全局统一规则)
如果项目中所有存入MongoDB的模型都需要自动转换UUID,可以自定义一个通用的BaseModel基类,重写dict()方法,后续所有业务模型都继承这个基类即可:
from uuid import UUID from datetime import datetime from pydantic import BaseModel as PydanticBaseModel class MongoBaseModel(PydanticBaseModel): def dict(self, *args, **kwargs): data = super().dict(*args, **kwargs) for k, v in data.items(): # 自动转换所有UUID字段为字符串 if isinstance(v, UUID): # 按需选择:str(v)是带横杠的标准格式,v.hex是无横杠的32位格式 data[k] = str(v) # 也可以在这里加datetime的自定义转换规则 # elif isinstance(v, datetime): # data[k] = int(v.timestamp()) return data # 业务模型直接继承即可 class TestModel(MongoBaseModel): id: UUID4 = Field(default_factory=uuid4) title: str = Field(default="") ts: datetime = Field(default_factory=datetime.utcnow) # 直接调用.dict()就自动完成转换 record = TestModel() collection.insert_one(record.dict())
方案3:Pydantic V2 字段序列化装饰器(灵活自定义单个字段)
如果你用的是Pydantic V2,可以用field_serializer装饰器单独指定某个字段的序列化逻辑,不需要改动全局规则:
from uuid import UUID, uuid4 from pydantic import BaseModel, Field, field_serializer class TestModel(BaseModel): id: UUID = Field(default_factory=uuid4) title: str = Field(default="") @field_serializer("id") def serialize_id(self, value: UUID) -> str: # 自定义UUID的输出格式 return value.hex
内容的提问来源于stack exchange,提问作者qangdev
相关产品推荐
相关产品推荐

