Skip to content

Commit bb0eb62

Browse files
authored
Fix allOf multi-ref to preserve inheritance with property overrides (#2838)
1 parent ed67f88 commit bb0eb62

4 files changed

Lines changed: 68 additions & 5 deletions

File tree

src/datamodel_code_generator/parser/jsonschema.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1767,7 +1767,8 @@ def _merge_all_of_object(self, obj: JsonSchemaObject) -> JsonSchemaObject | None
17671767
"""Merge allOf items when they share object properties to avoid duplicate models.
17681768
17691769
Skip merging when there is exactly one $ref (inheritance with property overrides).
1770-
Continue merging when multiple $refs share properties to avoid duplicate fields.
1770+
Continue merging when multiple $refs have conflicting property definitions to avoid MRO issues.
1771+
Child property overrides (obj.properties) are not considered conflicts.
17711772
"""
17721773
ref_count = sum(1 for item in obj.allOf if item.ref)
17731774
if ref_count == 1:
@@ -1782,10 +1783,6 @@ def _merge_all_of_object(self, obj: JsonSchemaObject) -> JsonSchemaObject | None
17821783
for prop_name, prop_schema in resolved_item.properties.items():
17831784
property_signatures.setdefault(prop_name, set()).add(self._schema_signature(prop_schema))
17841785

1785-
if obj.properties:
1786-
for prop_name, prop_schema in obj.properties.items():
1787-
property_signatures.setdefault(prop_name, set()).add(self._schema_signature(prop_schema))
1788-
17891786
if not any(len(signatures) > 1 for signatures in property_signatures.values()):
17901787
return None
17911788

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# generated by datamodel-codegen:
2+
# filename: all_of_multi_ref_with_property_override.json
3+
# timestamp: 2019-07-26T00:00:00+00:00
4+
5+
from __future__ import annotations
6+
7+
from pydantic import BaseModel, constr
8+
9+
10+
class Thing(BaseModel):
11+
type: str
12+
name: constr(min_length=1)
13+
14+
15+
class Location(BaseModel):
16+
address: constr(min_length=5)
17+
18+
19+
class Person(Thing, Location):
20+
type: str | None = 'playground:Person'
21+
name: constr(min_length=1) | None = None
22+
age: int | None = None
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"$id": "https://example.com/person.schema.json",
4+
"title": "Person",
5+
"$defs": {
6+
"Thing": {
7+
"type": "object",
8+
"properties": {
9+
"type": { "type": "string" },
10+
"name": { "type": "string", "minLength": 1 }
11+
},
12+
"required": ["type", "name"]
13+
},
14+
"Location": {
15+
"type": "object",
16+
"properties": {
17+
"address": { "type": "string", "minLength": 5 }
18+
},
19+
"required": ["address"]
20+
}
21+
},
22+
"type": "object",
23+
"allOf": [
24+
{ "$ref": "#/$defs/Thing" },
25+
{ "$ref": "#/$defs/Location" }
26+
],
27+
"properties": {
28+
"type": { "default": "playground:Person" },
29+
"name": { "minLength": 2 },
30+
"age": { "type": "integer" }
31+
}
32+
}

tests/main/jsonschema/test_main_jsonschema.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,6 +1411,18 @@ def test_main_all_of_ref_with_property_override(output_file: Path) -> None:
14111411
)
14121412

14131413

1414+
def test_main_all_of_multi_ref_with_property_override(output_file: Path) -> None:
1415+
"""Test allOf with multiple $refs preserves multi-inheritance when properties are overridden."""
1416+
with chdir(JSON_SCHEMA_DATA_PATH):
1417+
run_main_and_assert(
1418+
input_path=Path("all_of_multi_ref_with_property_override.json"),
1419+
output_path=output_file,
1420+
input_file_type="jsonschema",
1421+
assert_func=assert_file_content,
1422+
expected_file="all_of_multi_ref_with_property_override.py",
1423+
)
1424+
1425+
14141426
@pytest.mark.skipif(
14151427
black.__version__.split(".")[0] >= "24",
14161428
reason="Installed black doesn't support the old style",

0 commit comments

Comments
 (0)