Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allOf with a single $ref with a local json-pointer is resolved in the importing schema #2086

Open
simontaurus opened this issue Sep 8, 2024 · 0 comments

Comments

@simontaurus
Copy link

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.

if get_model_by_path(self.raw_obj, single_obj.ref[2:].split('/')).get(

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant