Skip to content

Instantly share code, notes, and snippets.

@dhermes
Created December 20, 2024 19:05
Show Gist options
  • Save dhermes/0d10e9a93996a66e255a9a766ae2508b to your computer and use it in GitHub Desktop.
Save dhermes/0d10e9a93996a66e255a9a766ae2508b to your computer and use it in GitHub Desktop.
[2024-12-20] `pydantic` transforming wrong zero-value container

Transforming {} to []

$ python transformed.py
{'points': []}
{'points': []}
`grid3` failed as expected
{'points': [{'x': 3, 'y': 4}]}
{'points': [{'x': 3, 'y': 4}, {'x': 5, 'y': 12}]}
`grid6` failed as expected

Allowing polymorphic type but only empty object

$ python polymorphic.py
{'points': []}
{'points': {}}
`grid3` failed as expected
{'points': [{'x': 3, 'y': 4}]}
{'points': [{'x': 3, 'y': 4}, {'x': 5, 'y': 12}]}
`grid6` failed as expected
from typing import List, Union
import pydantic
class _EmptyObject(pydantic.BaseModel):
model_config = pydantic.ConfigDict(extra="forbid")
class Point(pydantic.BaseModel):
x: int
y: int
class Grid(pydantic.BaseModel):
points: Union[List[Point], _EmptyObject]
def main():
grid1 = Grid.model_validate_json(b'{"points": []}')
print(grid1.model_dump())
grid2 = Grid.model_validate_json(b'{"points": {}}')
print(grid2.model_dump())
try:
grid3 = Grid.model_validate_json(b'{"points": {"cannot": "be_here"}}')
print(grid3.model_dump())
except pydantic.ValidationError:
print("`grid3` failed as expected")
grid4 = Grid.model_validate_json(b'{"points": [{"x": 3, "y": 4}]}')
print(grid4.model_dump())
grid5 = Grid.model_validate_json(
b'{"points": [{"x": 3, "y": 4}, {"x": 5, "y": 12}]}'
)
print(grid5.model_dump())
try:
grid6 = Grid.model_validate_json(b'{"points": [{"x": 3}]}')
print(grid6.model_dump())
except pydantic.ValidationError:
print("`grid6` failed as expected")
if __name__ == "__main__":
main()
from typing import Any, List, Union
import pydantic
class Point(pydantic.BaseModel):
x: int
y: int
class Grid(pydantic.BaseModel):
@pydantic.field_validator("points", mode="before")
@classmethod
def parse_points(cls, value: Any) -> Any:
if value == {}:
return []
return value
points: List[Point]
def main():
grid1 = Grid.model_validate_json(b'{"points": []}')
print(grid1.model_dump())
grid2 = Grid.model_validate_json(b'{"points": {}}')
print(grid2.model_dump())
try:
grid3 = Grid.model_validate_json(b'{"points": {"cannot": "be_here"}}')
print(grid3.model_dump())
except pydantic.ValidationError:
print("`grid3` failed as expected")
grid4 = Grid.model_validate_json(b'{"points": [{"x": 3, "y": 4}]}')
print(grid4.model_dump())
grid5 = Grid.model_validate_json(
b'{"points": [{"x": 3, "y": 4}, {"x": 5, "y": 12}]}'
)
print(grid5.model_dump())
try:
grid6 = Grid.model_validate_json(b'{"points": [{"x": 3}]}')
print(grid6.model_dump())
except pydantic.ValidationError:
print("`grid6` failed as expected")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment