Skip to content

Commit

Permalink
Fix Parsing of JSON Pydantic Object Id values
Browse files Browse the repository at this point in the history
* fix #940
  • Loading branch information
07pepa committed Oct 21, 2024
1 parent f9d79ff commit 34dad23
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 2 deletions.
12 changes: 10 additions & 2 deletions beanie/odm/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@
from pydantic_core.core_schema import (
ValidationInfo,
simple_ser_schema,
str_schema,
)
else:
from pydantic.fields import ModelField # type: ignore
Expand Down Expand Up @@ -159,7 +158,16 @@ def __get_pydantic_core_schema__(
) -> CoreSchema: # type: ignore
return core_schema.json_or_python_schema(
python_schema=plain_validator(cls.validate),
json_schema=str_schema(),
json_schema=plain_validator(
cls.validate,
metadata={
"pydantic_js_input_core_schema": core_schema.str_schema(
pattern="^[0-9a-f]{24}$",
min_length=24,
max_length=24,
)
},
),
serialization=core_schema.plain_serializer_function_ser_schema(
lambda instance: str(instance), when_used="json"
),
Expand Down
32 changes: 32 additions & 0 deletions tests/odm/test_id.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
from uuid import UUID

import pytest
from pydantic import BaseModel

from beanie import PydanticObjectId
from beanie.odm.utils.pydantic import IS_PYDANTIC_V2
from tests.odm.models import DocumentWithCustomIdInt, DocumentWithCustomIdUUID


Expand All @@ -15,3 +20,30 @@ async def test_integer_id():
await doc.insert()
new_doc = await DocumentWithCustomIdInt.get(doc.id)
assert isinstance(new_doc.id, int)


if IS_PYDANTIC_V2:

class A(BaseModel):
id: PydanticObjectId

async def test_pydantic_object_id_validation_json():
deserialized = A.model_validate_json(
'{"id": "5eb7cf5a86d9755df3a6c593"}'
)
assert isinstance(deserialized.id, PydanticObjectId)
assert str(deserialized.id) == "5eb7cf5a86d9755df3a6c593"
assert deserialized.id == PydanticObjectId("5eb7cf5a86d9755df3a6c593")

@pytest.mark.parametrize(
"data",
[
"5eb7cf5a86d9755df3a6c593",
PydanticObjectId("5eb7cf5a86d9755df3a6c593"),
],
)
async def test_pydantic_object_id_serialization(data):
deserialized = A(**{"id": data})
assert isinstance(deserialized.id, PydanticObjectId)
assert str(deserialized.id) == "5eb7cf5a86d9755df3a6c593"
assert deserialized.id == PydanticObjectId("5eb7cf5a86d9755df3a6c593")

0 comments on commit 34dad23

Please sign in to comment.