Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/datamodel_code_generator/parser/jsonschema.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,14 +460,19 @@ def has_ref_with_schema_keywords(self) -> bool:
"""Check if schema has $ref combined with schema-affecting keywords.

Metadata-only keywords (title, description, etc.) are excluded
as they don't affect the schema structure.
as they don't affect the schema structure. OpenAPI/JSON Schema
extension fields (x-*) are also excluded as they are vendor
extensions and don't affect the core schema structure.
"""
if not self.ref:
return False
other_fields = get_fields_set(self) - {"ref"}
schema_affecting_fields = other_fields - self.__metadata_only_fields__ - {"extras"}
if self.extras:
schema_affecting_extras = {k for k in self.extras if k not in self.__metadata_only_fields__}
# Filter out metadata-only fields AND extension fields (x-* prefix)
schema_affecting_extras = {
k for k in self.extras if k not in self.__metadata_only_fields__ and not k.startswith("x-")
}
if schema_affecting_extras:
schema_affecting_fields |= {"extras"}
return bool(schema_affecting_fields)
Expand Down
25 changes: 25 additions & 0 deletions tests/parser/test_jsonschema.py
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,31 @@ def test_has_ref_with_schema_keywords_extras_with_metadata_only_keys() -> None:
assert obj.has_ref_with_schema_keywords is False


def test_has_ref_with_schema_keywords_extras_with_extension_keys() -> None:
"""Test has_ref_with_schema_keywords when extras contains only x-* extension keys.

OpenAPI/JSON Schema extension fields (x-*) should be treated as metadata
and not trigger schema merging, which prevents infinite recursion with
self-referencing schemas.
"""
# x-* extensions are vendor extensions, should not trigger merge
obj = model_validate(
JsonSchemaObject,
{
"$ref": "#/$defs/Base",
"deprecated": False, # metadata-only field
"x-internalAPI": False, # extension field
"x-custom-field": "value", # another extension field
},
)
# Verify extras contains extension keys
assert obj.extras
assert "x-internalAPI" in obj.extras
assert "x-custom-field" in obj.extras
# Extension fields should NOT trigger schema merge
assert obj.has_ref_with_schema_keywords is False


def test_has_ref_with_schema_keywords_no_extras() -> None:
"""Test has_ref_with_schema_keywords when extras is empty."""
# Only $ref and a schema-affecting field, no extras
Expand Down
Loading