Skip to content

Commit

Permalink
Add support for external referenced discriminators (#1991)
Browse files Browse the repository at this point in the history
Co-authored-by: Koudai Aono <[email protected]>
  • Loading branch information
luca-knaack-webcom and koxudaxi authored Jun 10, 2024
1 parent e68629d commit b1c0f22
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 2 deletions.
6 changes: 4 additions & 2 deletions datamodel_code_generator/parser/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -778,8 +778,10 @@ def __apply_discriminator_type(
discriminator_model.path.split('#/')[-1]
!= path.split('#/')[-1]
):
# TODO: support external reference
continue
if '#' in path or discriminator_model.path[
:-1
] != path.lstrip('./'):
continue
type_names.append(name)
else:
type_names = [discriminator_model.path.split('/')[-1]]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# generated by datamodel-codegen:
# filename: schema.json
# timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from typing import Union

from pydantic import BaseModel, Field
from typing_extensions import Literal


class Type1(BaseModel):
type_: Literal['a'] = Field('a', title='Type ')


class Type2(BaseModel):
type_: Literal['b'] = Field('b', title='Type ')


class Type3(BaseModel):
type_: Literal['c'] = Field('c', title='Type ')


class Response(BaseModel):
inner: Union[Type1, Type2, Type3] = Field(..., discriminator='type_', title='Inner')
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"properties": {
"type_": {
"const": "a",
"default": "a",
"title": "Type "
}
},
"title": "Type1",
"type": "object"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"$def": {
"Type3": {
"properties": {
"type_": {
"const": "c",
"default": "c",
"title": "Type "
}
},
"title": "Type3",
"type": "object"
}
},
"properties": {
"inner": {
"discriminator": {
"mapping": {
"a": "./artificial_folder/type1.json",
"b": "./type2.json",
"c": "#/$def/Type3"
},
"propertyName": "type_"
},
"oneOf": [
{
"$ref": "./artificial_folder/type1.json"
},
{
"$ref": "./type2.json"
},
{
"$ref": "#/$def/Type3"
}
],
"title": "Inner"
}
},
"required": [
"inner"
],
"title": "Response",
"type": "object"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"properties": {
"type_": {
"const": "b",
"default": "b",
"title": "Type "
}
},
"title": "Type2",
"type": "object"
}
29 changes: 29 additions & 0 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -6123,6 +6123,35 @@ def test_main_jsonschema_discriminator_literals():
)


@freeze_time('2019-07-26')
def test_main_jsonschema_external_discriminator():
with TemporaryDirectory() as output_dir:
output_file: Path = Path(output_dir) / 'output.py'
return_code: Exit = main(
[
'--input',
str(
JSON_SCHEMA_DATA_PATH
/ 'discriminator_with_external_reference'
/ 'schema.json'
),
'--output',
str(output_file),
'--output-model-type',
'pydantic_v2.BaseModel',
]
)
assert return_code == Exit.OK
assert (
output_file.read_text()
== (
EXPECTED_MAIN_PATH
/ 'discriminator_with_external_reference'
/ 'output.py'
).read_text()
)


@freeze_time('2019-07-26')
@pytest.mark.skipif(
black.__version__.split('.')[0] == '19',
Expand Down

0 comments on commit b1c0f22

Please sign in to comment.