datamodel-code-generator
datamodel-code-generator copied to clipboard
Model class names are missing the last letter in models generated from 2020-12 JSON schema specification
Describe the bug
When generating data models from the 2020-12 JSON schema specification, all direct subclasses of BaseModel are missing the last letter in their class name. For example:
class Unevaluate(BaseModel):
unevaluatedItems: Optional[Any] = None
unevaluatedProperties: Optional[Any] = None
This class should generate with the name Unevaluated, but it instead generates with the name Unevaluate.
To Reproduce
Example schema: https://json-schema.org/draft/2020-12/schema
Used commandline:
$ datamodel-codegen --url https://json-schema.org/draft/2020-12/schema --input-file-type jsonschema --output model.py --output-model-type pydantic_v2.BaseModel
Expected behavior
The expected behaviour is for the class names to not be missing the final letter in their names.
Version:
- OS: macOS 14.5
- Python version: 3.12.3
- datamodel-code-generator version: 0.25.8
Additional context
I'm pretty sure I know how to fix this, but I don't feel like I have enough context to understand all the implications of this change.
In reference.py at line 567, we have this piece of code:
if len(split_ref) == 1:
original_name = Path(
split_ref[0][:-1] if self.is_external_root_ref(path) else split_ref[0]
).stem
else:
original_name = (
Path(split_ref[1][:-1]).stem
if self.is_external_root_ref(path)
else split_ref[1]
)
The problem seems to happen in the case where ref does not have the ending #, but the path does. For example, when path is 'https://json-schema.org/draft/2020-12/meta/core#' and ref is 'meta/core'. In this case, it seems you can replace the [:1] indexing with .rstrip('#') to make it so that it will still drop the # without ever cutting off the end of the word.
if len(split_ref) == 1:
original_name = Path(
split_ref[0].rstrip('#')
if self.is_external_root_ref(path)
else split_ref[0]
).stem
else:
original_name = (
Path(split_ref[1].rstrip('#')).stem
if self.is_external_root_ref(path)
else split_ref[1]
)
This code change does pass all of the tests, but I'm just not certain about whether this change is fixing the root cause or not. For all I know, the path having a # at the end and the ref not having one is the true root cause, I just don't feel like I have enough familiarity to say.
I have the same problem and would love to be able to have this fixed.