datamodel-code-generator
datamodel-code-generator copied to clipboard
allOf with a single $ref with a local json-pointer is resolved in the importing schema
Describe the bug
allOf with a single $ref with a local json-pointer in schemaA.json is not resolved correctly with schemaA.json is itself referenced from schemaB.json.
It seems like schemaB.json (where no definitions exist) is passed as self.raw_obj to get_model_by_path() but it should be schemaB.json. get_model_by_path() tries to look up the path but fails.
https://github.com/koxudaxi/datamodel-code-generator/blob/222f71834296e36ec1b013a65344b2adb40b7cf7/datamodel_code_generator/parser/jsonschema.py#L871
To Reproduce
schemaA
{
"definitions": {
"generated": {
"type": "object",
"title": "SchemaAGenerated",
"properties": {
"test": {
"title": "test",
"type": "string"
}
}
}
},
"title": "SchemaA",
"allOf": [
{
"$ref": "#/definitions/generated"
}
]
}
schemaB.json
{
"allOf": [
{
"$ref": "SchemaA.json"
}
],
"type": "object",
"title": "SchemaB"
}
Used commandline:
$ datamodel-codegen --input schemaB.json --output model.py --use-title-as-name
Error:
File ".venv\lib\site-packages\datamodel_code_generator\parser\jsonschema.py", line 1807, in _parse_file
self.parse_obj(obj_name, root_obj, path_parts or ['#'])
File ".venv\lib\site-packages\datamodel_code_generator\parser\jsonschema.py", line 1667, in parse_obj
self.parse_all_of(name, obj, path)
File ".venv\lib\site-packages\datamodel_code_generator\parser\jsonschema.py", line 871, in parse_all_of
if get_model_by_path(self.raw_obj, single_obj.ref[2:].split('/')).get(
File ".venv\lib\site-packages\datamodel_code_generator\parser\jsonschema.py", line 87, in get_model_by_path
model = get_model_by_path(schema[keys[0]], keys[1:]) # type: ignore
KeyError: 'definitions'
Expected behavior No exception and the following model.py
class SchemaAGenerated(BaseModel):
test: Optional[str] = Field(
None, title="test"
)
class SchemaA(SchemaAGenerated):
pass
class SchemaB(SchemaA):
pass
or, even better, with the empty class SchemaA merged with SchemaAGenerated
class SchemaA(BaseModel):
test: Optional[str] = Field(
None, title="test"
)
class SchemaB(SchemaA):
pass
Workarounds: replacing
"allOf": [
{
"$ref": "#/definitions/generated"
}
]
with
"$ref": "#/definitions/generated"
works, but produces
class SchemaAGenerated(BaseModel):
test: Optional[str] = Field(None, title='test')
class SchemaA(BaseModel):
__root__: SchemaAGenerated = Field(..., title='SchemaA')
class SchemaB(BaseModel):
pass
even with --collapse-root-models.
Having an array of two $refs in allOf also works as expected:
"allOf": [
{
"$ref": "#/definitions/generated"
},
{
}
]
Version:
- OS: Windows 10
- Python version: 3.11 | 3.9
- datamodel-code-generator version: 0.25.6 | 0.26.0