File tree Expand file tree Collapse file tree
src/datamodel_code_generator/parser Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -1618,6 +1618,16 @@ def get_discriminator_field_value(
16181618 if discriminator_value is not None :
16191619 discriminator_values = [discriminator_value ]
16201620 break
1621+ # Reuse models are created as empty subclasses with a "/reuse" path suffix.
1622+ # Scan inherited fields to recover the discriminator literal from the base.
1623+ if not discriminator_values and discriminator_model .path .endswith ("/reuse" ):
1624+ for discriminator_field in discriminator_model .iter_all_fields (): # pragma: no branch
1625+ if field_name not in {discriminator_field .original_name , discriminator_field .name }:
1626+ continue
1627+ discriminator_value = get_discriminator_field_value (discriminator_field )
1628+ if discriminator_value is not None : # pragma: no branch
1629+ discriminator_values = [discriminator_value ]
1630+ break
16211631
16221632 if not discriminator_values and mapping :
16231633 check_paths (discriminator_model , mapping ) # ty: ignore
Original file line number Diff line number Diff line change 1+ # generated by datamodel-codegen:
2+ # filename: reuse_model_discriminator_literal.json
3+ # timestamp: 2019-07-26T00:00:00+00:00
4+
5+ from __future__ import annotations
6+
7+ from typing import Literal
8+
9+ from pydantic import BaseModel , Field
10+
11+
12+ class SignalId (BaseModel ):
13+ domain : str
14+ source : Literal ['catalog' ]
15+
16+
17+ class SignalId1 (BaseModel ):
18+ url : str
19+ source : Literal ['agent' ]
20+
21+
22+ class FirstThing (BaseModel ):
23+ signal_id : SignalId | SignalId1 | None = Field (
24+ None , discriminator = 'source' , title = 'Signal ID'
25+ )
26+
27+
28+ class SignalId2 (SignalId ):
29+ source : Literal ['catalog' ]
30+
31+
32+ class SignalId3 (SignalId1 ):
33+ source : Literal ['agent' ]
34+
35+
36+ class SecondThing (BaseModel ):
37+ signal_id : SignalId2 | SignalId3 | None = Field (
38+ None , discriminator = 'source' , title = 'Signal ID'
39+ )
40+
41+
42+ class Root (BaseModel ):
43+ first_thing : FirstThing | None = None
44+ second_thing : SecondThing | None = None
Original file line number Diff line number Diff line change 1+ {
2+ "$schema" : " http://json-schema.org/draft-07/schema#" ,
3+ "title" : " Root" ,
4+ "type" : " object" ,
5+ "properties" : {
6+ "first_thing" : {
7+ "type" : " object" ,
8+ "properties" : {
9+ "signal_id" : {
10+ "title" : " Signal ID" ,
11+ "discriminator" : {
12+ "propertyName" : " source"
13+ },
14+ "oneOf" : [
15+ {
16+ "type" : " object" ,
17+ "properties" : {
18+ "domain" : {
19+ "type" : " string"
20+ },
21+ "source" : {
22+ "const" : " catalog"
23+ }
24+ },
25+ "required" : [
26+ " source" ,
27+ " domain"
28+ ]
29+ },
30+ {
31+ "type" : " object" ,
32+ "properties" : {
33+ "url" : {
34+ "type" : " string"
35+ },
36+ "source" : {
37+ "const" : " agent"
38+ }
39+ },
40+ "required" : [
41+ " source" ,
42+ " url"
43+ ]
44+ }
45+ ]
46+ }
47+ }
48+ },
49+ "second_thing" : {
50+ "type" : " object" ,
51+ "properties" : {
52+ "signal_id" : {
53+ "title" : " Signal ID" ,
54+ "discriminator" : {
55+ "propertyName" : " source"
56+ },
57+ "oneOf" : [
58+ {
59+ "type" : " object" ,
60+ "properties" : {
61+ "domain" : {
62+ "type" : " string"
63+ },
64+ "source" : {
65+ "const" : " catalog"
66+ }
67+ },
68+ "required" : [
69+ " source" ,
70+ " domain"
71+ ]
72+ },
73+ {
74+ "type" : " object" ,
75+ "properties" : {
76+ "url" : {
77+ "type" : " string"
78+ },
79+ "source" : {
80+ "const" : " agent"
81+ }
82+ },
83+ "required" : [
84+ " source" ,
85+ " url"
86+ ]
87+ }
88+ ]
89+ }
90+ }
91+ }
92+ }
93+ }
Original file line number Diff line number Diff line change @@ -1214,6 +1214,26 @@ def test_main_reuse_model_collapse_inline_definitions(output_file: Path) -> None
12141214 )
12151215
12161216
1217+ def test_main_reuse_model_discriminator_literal (output_file : Path ) -> None :
1218+ """Reuse inherited discriminator literals instead of injecting the reuse path segment."""
1219+ run_main_and_assert (
1220+ input_path = JSON_SCHEMA_DATA_PATH / "reuse_model_discriminator_literal.json" ,
1221+ output_path = output_file ,
1222+ input_file_type = "jsonschema" ,
1223+ assert_func = assert_file_content ,
1224+ extra_args = [
1225+ "--reuse-model" ,
1226+ "--use-union-operator" ,
1227+ "--use-standard-collections" ,
1228+ "--output-model-type" ,
1229+ "pydantic_v2.BaseModel" ,
1230+ "--target-python-version" ,
1231+ "3.10" ,
1232+ ],
1233+ force_exec_validation = True ,
1234+ )
1235+
1236+
12171237def test_main_reuse_model_collapse_with_root (output_file : Path ) -> None :
12181238 """Test --reuse-model --collapse-reuse-models skips RootModel deduplication."""
12191239 run_main_and_assert (
You can’t perform that action at this time.
0 commit comments