Skip to content

Commit 294acb6

Browse files
Exclude OpenAPI/JSON Schema extension fields (x-*) (#2801)
Co-authored-by: Koudai Aono <koxudaxi@gmail.com>
1 parent 9dc9dd4 commit 294acb6

2 files changed

Lines changed: 32 additions & 2 deletions

File tree

src/datamodel_code_generator/parser/jsonschema.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -460,14 +460,19 @@ def has_ref_with_schema_keywords(self) -> bool:
460460
"""Check if schema has $ref combined with schema-affecting keywords.
461461
462462
Metadata-only keywords (title, description, etc.) are excluded
463-
as they don't affect the schema structure.
463+
as they don't affect the schema structure. OpenAPI/JSON Schema
464+
extension fields (x-*) are also excluded as they are vendor
465+
extensions and don't affect the core schema structure.
464466
"""
465467
if not self.ref:
466468
return False
467469
other_fields = get_fields_set(self) - {"ref"}
468470
schema_affecting_fields = other_fields - self.__metadata_only_fields__ - {"extras"}
469471
if self.extras:
470-
schema_affecting_extras = {k for k in self.extras if k not in self.__metadata_only_fields__}
472+
# Filter out metadata-only fields AND extension fields (x-* prefix)
473+
schema_affecting_extras = {
474+
k for k in self.extras if k not in self.__metadata_only_fields__ and not k.startswith("x-")
475+
}
471476
if schema_affecting_extras:
472477
schema_affecting_fields |= {"extras"}
473478
return bool(schema_affecting_fields)

tests/parser/test_jsonschema.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,31 @@ def test_has_ref_with_schema_keywords_extras_with_metadata_only_keys() -> None:
915915
assert obj.has_ref_with_schema_keywords is False
916916

917917

918+
def test_has_ref_with_schema_keywords_extras_with_extension_keys() -> None:
919+
"""Test has_ref_with_schema_keywords when extras contains only x-* extension keys.
920+
921+
OpenAPI/JSON Schema extension fields (x-*) should be treated as metadata
922+
and not trigger schema merging, which prevents infinite recursion with
923+
self-referencing schemas.
924+
"""
925+
# x-* extensions are vendor extensions, should not trigger merge
926+
obj = model_validate(
927+
JsonSchemaObject,
928+
{
929+
"$ref": "#/$defs/Base",
930+
"deprecated": False, # metadata-only field
931+
"x-internalAPI": False, # extension field
932+
"x-custom-field": "value", # another extension field
933+
},
934+
)
935+
# Verify extras contains extension keys
936+
assert obj.extras
937+
assert "x-internalAPI" in obj.extras
938+
assert "x-custom-field" in obj.extras
939+
# Extension fields should NOT trigger schema merge
940+
assert obj.has_ref_with_schema_keywords is False
941+
942+
918943
def test_has_ref_with_schema_keywords_no_extras() -> None:
919944
"""Test has_ref_with_schema_keywords when extras is empty."""
920945
# Only $ref and a schema-affecting field, no extras

0 commit comments

Comments
 (0)