Reputation: 627
I am trying to parse MongoDB data to a pydantic schema but fail to read its _id
field which seem to just disappear from the schema.
The issue is definitely related to the underscore in front of the object attribute. I can't change _id
field name since that would imply not parsing the field at all.
Please find below the code I use (using int
instead of ObjectId
for the sake of simplification)
from pydantic import BaseModel
class User_1(BaseModel):
_id: int
data_1 = {"_id": 1}
parsed_1 = User_1(**data_1)
print(parsed_1.schema())
class User_2(BaseModel):
id: int
data_2 = {"id": 1}
parsed_2 = User_2(**data_2)
print(parsed_2.schema())
User_1
is parsed successfully since its _id
field is required but can't be read afterwards.
User_2
works in the above example by fails if attached to Mongo which doesn't provide any id
field but _id
.
Output of the code above reads as follows:
User_1 {'title': 'User_1', 'type': 'object', 'properties': {}}
User_2 {'title': 'User_2', 'type': 'object', 'properties': {'id': {'title': 'Id', 'type': 'integer'}}, 'required': ['id']}
Upvotes: 24
Views: 21431
Reputation: 125
The other two answers don't work for me, I don't know why. Maybe the versions are deprecated, here is the updated answer:
from pydantic import Field
from bson import ObjectId
from typing import Optional
id: Optional[ObjectId] = Field(alias='_id')
title: str
cover: str
class Config:
json_encoders = {
ObjectId: str
}
arbitrary_types_allowed = True
Upvotes: -1
Reputation: 66
I know that you had asked this ages ago, but for anyone else still struggling with it here's a suggested solution by MongoDb
When applying their solution we get the following code.
from typing import Optional, Annotated
from pydantic import BaseModel, Field, BeforeValidator
PyObjectId = Annotated[str, BeforeValidator(str)]
class User_1(BaseModel):
id: Optional[PyObjectId] = Field(alias="_id", default=None)
All the validation and model conversions work just fine, without any class Config, or other workarounds. Hope this helps somebody.
Upvotes: 5
Reputation: 13349
you need to use an alias for that field name
from pydantic import BaseModel, Field
class User_1(BaseModel):
id: int = Field(..., alias='_id')
See the docs here.
Upvotes: 36