FastAPI POST路由中ObjectId引发JSON Schema生成错误排查
解决FastAPI中Pydantic无法生成ObjectId的JSON Schema问题
问题根源
Pydantic默认不支持bson.objectid.ObjectId类型的JSON Schema生成,不管是模型里的Projects列表字段,还是POST请求中传递的ID,只要直接使用原生ObjectId,都会触发PydanticInvalidForJsonSchema错误。
具体解决方案
1. 自定义Pydantic类型适配ObjectId
自己实现一个兼容Pydantic的ObjectId类型,处理序列化和Schema生成逻辑:
from bson import ObjectId from pydantic_core import core_schema from pydantic import GetCoreSchemaHandler from pydantic.json_schema import JsonSchemaValue class PyObjectId(ObjectId): @classmethod def __get_pydantic_core_schema__(cls, source_type: type, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: # 定义Python层面的校验和序列化规则 return core_schema.json_or_python( json_schema=core_schema.str_schema(), python_schema=core_schema.is_instance(ObjectId), serialization=core_schema.plain_serializer_function_ser_schema(str), ) @classmethod def __get_pydantic_json_schema__(cls, schema: core_schema.CoreSchema, handler) -> JsonSchemaValue: # 指定JSON Schema的类型为字符串 return {"type": "string"}
之后在你的模型里用这个PyObjectId替代原生的ObjectId即可。
2. 直接使用Pydantic内置的PyObjectId(Pydantic v2+)
如果你的项目用的是Pydantic v2及以上版本,官方已经提供了MongoDB ObjectId的适配类型,直接导入使用:
from pydantic import PyObjectId, BaseModel, Field # 示例Project模型 class Project(BaseModel): id: PyObjectId = Field(default_factory=PyObjectId, alias="_id") name: str # 示例User模型 class User(BaseModel): projects: list[PyObjectId] = []
3. 配置模型的JSON编码器(辅助方案)
如果只是需要序列化ObjectId为字符串返回前端,可以在模型中添加json_encoders配置,但这个方案无法解决JSON Schema生成的问题,仅作为补充:
from bson import ObjectId from pydantic import BaseModel class User(BaseModel): projects: list[ObjectId] = [] model_config = { "json_encoders": { ObjectId: lambda oid: str(oid) } }
4. 规范POST请求的ID传递方式
前端传递ID时必须用字符串格式(比如"60d21b4667d0d8992e610c85"),后端收到后再转为ObjectId对象,不要直接传递ObjectId类型(前端无法生成该类型)。
内容的提问来源于stack exchange,提问作者learn.boy
相关产品推荐
相关产品推荐

