datamodel-code-generator
datamodel-code-generator copied to clipboard
Referenced basic types (like strings) are converted to classes
Describe the bug If a string is referenced, it is turned into a separate class that wraps the string.
To Reproduce
Given this schema:
{
"openapi" : "3.0.0",
"components" : {
"schemas" : {
"UserId" : {
"type" : "string",
},
"Tweet" : {
"type" : "object",
"properties" : {
"author_id" : {
"$ref" : "#/components/schemas/UserId"
}
}
}
}
}
}
datamodel-code-generator emits:
# generated by datamodel-codegen:
# filename: minimal.json
# timestamp: 2022-08-10T13:22:26+00:00
from __future__ import annotations
from typing import Optional
from pydantic import BaseModel, constr
class UserId(BaseModel):
__root__: str
class Tweet(BaseModel):
author_id: Optional[UserId] = None
Would it be difficult to directly use a string in those cases?
Version:
- OS: Ubuntu 20.04
- Python version: 3.8.10
- datamodel-code-generator version: 0.13.0
@Trolldemorted The CLI doesn't provide a solution. We should implement a new option. What do you expect?
class Tweet(BaseModel):
author_id: Optional[str] = None
Or,
UserId = str
class Tweet(BaseModel):
author_id: Optional[UserId] = None
🤔
The first one looks way better, keeping things simple is always good :)
This works fine for single references, but if a definition is referenced multiple times it causes all field attributes (e.g. Annotated[str, Field(regex='...', description='...')]
) to be duplicated unnecessarily for each field. This makes keeping the output model internally consistent more difficult when editing it manually.
While i think this change has some uses, I'd prefer a choice between "force inline", "force class" and potentially "auto", which would check the reference count to decide on a case by case basis.
@Trolldemorted @Trolldemorted @Dominic-Walther
I have released the new version as 0.14.1. The version has this option.
--collapse-root-models
Models generated with a root-type field will be
merged into the models using that root-type model
@koxudaxi Thank you for implementing the feature. With the given test scheme everything works as expected. We tried the slightly larger Twitter API specification as source and get the following error:
Traceback (most recent call last):
File "/home/username/.local/lib/python3.8/site-packages/datamodel_code_generator/__main__.py", line 626, in main
generate(
File "/home/username/.local/lib/python3.8/site-packages/datamodel_code_generator/__init__.py", line 384, in generate
results = parser.parse()
File "/home/username/.local/lib/python3.8/site-packages/datamodel_code_generator/parser/base.py", line 802, in parse
model_to_models[unused_model].remove(unused_model)
ValueError: list.remove(x): x not in list
We used this command with the 0.15.0 release:
datamodel-codegen --input openapi.json --input-file-type openapi --output model.py --collapse-root-models
.
Without --collapse-root-models
the code is created successfully.
Should we create a new issue?
@anneum
Thank you for testing the new version.
Yes, this is a bug.
I fixed the problem
https://github.com/koxudaxi/datamodel-code-generator/pull/997/files#diff-34a68196dba5b4f2cef091ddb835f794178254d4c94bff4a84f84e546f2f6db7R802-R803
I merged the PR. But I have not released it yet.
you can try it with pip install git+https://github.com/koxudaxi/datamodel-code-generator.git
Also, I checked the Twitter API specification with the master branch, and some root models have gone. But, some type-hint references the deleted root model. I will fix it soon.
@anneum
I have released the fixed version 0.16.0
Thank you very much!!