datamodel-code-generator
datamodel-code-generator copied to clipboard
output-model-type `pydantic_2.BaseModel` with `Field()` generates invalid pydantic v2 classes
Describe the bug
Generating "pydantic_v2.BaseModel
with Field()
generates an impossible solution for current pydantic v2 implementation.
To Reproduce
Example schema:
{
"$schema": "http://json-schema.org/draft-07/schema",
"properties": {
"Settings": {
"title": "having a title will force a Field()",
"properties": {
"name": {
"type": "string"
}
},
"required": ["name"],
"type": "object"
}
},
"required": ["Settings"],
"type": "object"
}
Used commandline:
$ datamodel-codegen --input-file-type jsonschema --output-model-type "pydantic_v2.BaseModel" --input sample.json --output generated_classes.py
Expected behavior The generated class should work when running with pydantic v2.
Version:
- OS:
Fedora 38 - Linux-6.1.50-200.fc38.x86_64-x86_64-with-glibc2.37
- Python version:
3.11.4 (main, Jun 7 2023, 00:00:00) [GCC 13.1.1 20230511 (Red Hat 13.1.1-2)]
- datamodel-code-generator version:
0.21.4
Additional context The generate class is the following:
from __future__ import annotations
from pydantic import BaseModel, Field
class Settings(BaseModel):
name: str
class Model(BaseModel):
Settings: Settings = Field(
..., title='having a title will force field defined with Field()'
)
Which is exactly the same as the one generated with --output-model-type "pydantic.BaseModel"
. However, due to pydantic v2 limitations, the generated class will lead to a pydantic v2 error: RecursionError: maximum recursion depth exceeded
The pydantic v1 and v2 behaviour duality has been reported at pydantic repository: https://github.com/pydantic/pydantic/issues/7327
To make datamodel-code-generator work with the current pydantic v2 implementation, as suggested by https://github.com/pydantic/pydantic/issues/7327#issuecomment-1706012608, generated classes must have a different name from the field names, like so:
from __future__ import annotations
from pydantic import BaseModel, Field
class Settings_(BaseModel):
name: str
class Model(BaseModel):
Settings: Settings_ = Field(
..., title='having a title will force field defined with Field()'
)
In which, having a class name that doesn't collide with field name, makes the generated class to work with pydantic v2.
Thank you for creating the issue. I didn't know the behavior. I will fix it.
I may change the field name instead of the Model name.
🤔 Any updates ?
I had the same issue. I solved it by using the --use-annotated
flag. However, I still it would be helpful if the root cause is addressed.