diff --git a/src/datamodel_code_generator/model/pydantic/base_model.py b/src/datamodel_code_generator/model/pydantic/base_model.py index 6368a9379..1007eba33 100644 --- a/src/datamodel_code_generator/model/pydantic/base_model.py +++ b/src/datamodel_code_generator/model/pydantic/base_model.py @@ -220,7 +220,7 @@ def __str__(self) -> str: # noqa: PLR0912 elif isinstance(discriminator, dict): # pragma: no cover data["discriminator"] = discriminator["propertyName"] - if self.required: + if self.required and not self.has_default: default_factory = None elif self.default is not UNDEFINED and self.default is not None and "default_factory" not in data: default_factory = self._get_default_as_pydantic_model() @@ -249,7 +249,7 @@ def __str__(self) -> str: # noqa: PLR0912 if self.use_annotated: field_arguments = self._process_annotated_field_arguments(field_arguments) - elif self.required: + elif self.required and not default_factory: field_arguments = ["...", *field_arguments] elif not default_factory: default_repr = repr_set_sorted(self.default) if isinstance(self.default, set) else repr(self.default) diff --git a/tests/data/expected/main/jsonschema/has_default_value.py b/tests/data/expected/main/jsonschema/has_default_value.py index fa29c4440..bc013ec5a 100644 --- a/tests/data/expected/main/jsonschema/has_default_value.py +++ b/tests/data/expected/main/jsonschema/has_default_value.py @@ -25,11 +25,17 @@ class Pet(BaseModel): class Family(BaseModel): - __root__: list[ID] = ['abc', 'efg'] + __root__: list[ID] = Field( + default_factory=lambda: [ID.parse_obj(v) for v in ['abc', 'efg']] + ) class FamilyPets(BaseModel): - __root__: list[Pet] = ['taro', 'shiro'] + __root__: list[Pet] = Field( + default_factory=lambda: [ + Pet.parse_obj(v) for v in [{'name': 'taro'}, {'name': 'shiro'}] + ] + ) class Person(BaseModel): diff --git a/tests/data/expected/main/jsonschema/has_default_value_pydantic_v2.py b/tests/data/expected/main/jsonschema/has_default_value_pydantic_v2.py new file mode 100644 index 000000000..317265c98 --- /dev/null +++ b/tests/data/expected/main/jsonschema/has_default_value_pydantic_v2.py @@ -0,0 +1,48 @@ +# generated by datamodel-codegen: +# filename: has_default_value.json +# timestamp: 2019-07-26T00:00:00+00:00 + +from __future__ import annotations + +from enum import Enum + +from pydantic import BaseModel, Field, RootModel + + +class TeamType(Enum): + Department = 'Department' + Division = 'Division' + BusinessUnit = 'BusinessUnit' + Organization = 'Organization' + + +class ID(RootModel[str]): + root: str = 'abc' + + +class Pet(BaseModel): + name: str | None = None + + +class Family(RootModel[list[ID]]): + root: list[ID] = Field( + default_factory=lambda: [ID.model_validate(v) for v in ['abc', 'efg']] + ) + + +class FamilyPets(RootModel[list[Pet]]): + root: list[Pet] = Field( + default_factory=lambda: [ + Pet.model_validate(v) for v in [{'name': 'taro'}, {'name': 'shiro'}] + ] + ) + + +class Person(BaseModel): + id: ID | None = Field(default_factory=lambda: ID('abc')) + user: Pet | None = None + firstName: str | None = Field(None, description="The person's first name.") + team: TeamType | None = 'Department' + anotherTeam: TeamType | None = 'Department' + Family_1: Family | None = Field(None, alias='Family') + FamilyPets_1: FamilyPets | None = Field(None, alias='FamilyPets') diff --git a/tests/data/jsonschema/has_default_value.json b/tests/data/jsonschema/has_default_value.json index 288748b32..3d821af89 100644 --- a/tests/data/jsonschema/has_default_value.json +++ b/tests/data/jsonschema/has_default_value.json @@ -45,8 +45,8 @@ "$ref": "#/definitions/Pet" }, "default": [ - "taro", - "shiro" + {"name": "taro"}, + {"name": "shiro"} ] } }, diff --git a/tests/main/jsonschema/test_main_jsonschema.py b/tests/main/jsonschema/test_main_jsonschema.py index 74c728975..14fae9bdb 100644 --- a/tests/main/jsonschema/test_main_jsonschema.py +++ b/tests/main/jsonschema/test_main_jsonschema.py @@ -3254,14 +3254,26 @@ def test_jsonschema_use_title_as_name_nested_titles_pydantic(output_file: Path) ) -def test_main_jsonschema_has_default_value(output_file: Path) -> None: +@pytest.mark.parametrize( + ("output_model", "expected_file"), + [ + ("pydantic.BaseModel", "has_default_value.py"), + pytest.param( + "pydantic_v2.BaseModel", + "has_default_value_pydantic_v2.py", + marks=PYDANTIC_V2_SKIP, + ), + ], +) +def test_main_jsonschema_has_default_value(output_model: str, expected_file: str, output_file: Path) -> None: """Test default value handling.""" run_main_and_assert( input_path=JSON_SCHEMA_DATA_PATH / "has_default_value.json", output_path=output_file, input_file_type="jsonschema", assert_func=assert_file_content, - expected_file="has_default_value.py", + expected_file=expected_file, + extra_args=["--output-model-type", output_model], )