如何解决PyObjectId存入MongoDB时被转为字符串而非ObjectId的问题?
解决MongoDB存储ObjectId而非字符串的问题
你的问题核心在于PyObjectId类的序列化配置强制将ObjectId转换为字符串,导致存入MongoDB时无法保留原生ObjectId类型。以下是具体修复方案:
1. 修改PyObjectId的序列化逻辑
当前代码中serialization参数固定将ObjectId转为字符串,需要调整为仅在JSON序列化时转字符串,Python对象层面保留ObjectId实例:
from typing import Any from bson import ObjectId from pydantic_core import core_schema from pydantic import BaseModel, Field from datetime import datetime class PyObjectId(ObjectId): """To create a pydantic Object that validates bson ObjectID""" @classmethod def __get_pydantic_core_schema__(cls, _source_type: Any, _handler: Any) -> core_schema.CoreSchema: return core_schema.json_or_python_schema( json_schema=core_schema.str_schema(), python_schema=core_schema.union_schema( [ core_schema.is_instance_schema(ObjectId), core_schema.chain_schema( [ core_schema.str_schema(), core_schema.no_info_plain_validator_function(cls.validate), ] ), ] ), # 修改序列化逻辑:Python环境输出原生ObjectId,JSON环境输出字符串 serialization=core_schema.plain_serializer_function_ser_schema( lambda x: str(x) if core_schema.is_json_serialization() else x ), ) @classmethod def validate(cls, value) -> ObjectId: if not ObjectId.is_valid(value): raise ValueError("Invalid ObjectId") return ObjectId(value) class GoalRecordStored(BaseModel): """Goal Record Model.""" player_id: PyObjectId = Field(..., validation_alias="Player ID") date: datetime = Field(validation_alias="Date")
2. 存入MongoDB时使用正确的序列化模式
调用model_dump时,指定mode='python'以保留Python原生类型(包括ObjectId),同时加上by_alias=True确保使用MongoDB需要的字段别名:
# 示例:创建实例并存入MongoDB record = GoalRecordStored(**{"Player ID": "60d21b4667d0d8992e610c85", "Date": datetime.now()}) # 生成适合MongoDB的字典 mongo_data = record.model_dump(by_alias=True, mode='python') # 存入MongoDB(假设已有collection实例) collection.insert_one(mongo_data)
验证效果
执行上述代码后,MongoDB中的Player ID字段将以ObjectId类型存储,而非字符串。你可以通过MongoDB客户端查看字段类型确认。
内容的提问来源于stack exchange,提问作者ProxilityProblemSolver
相关产品推荐
相关产品推荐

