From cfc99ce92e84096372c1f2a753b0a842944e8f5f Mon Sep 17 00:00:00 2001 From: Marco Date: Fri, 5 Sep 2025 15:40:48 +0200 Subject: [PATCH 1/3] Issue 21890: Fixed flag to use for check of required, non-nullable map --- .../main/java/org/openapitools/codegen/CodegenConstants.java | 2 ++ .../main/java/org/openapitools/codegen/DefaultCodegen.java | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java index ae52412b7d2d..c299caf6063c 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java @@ -454,4 +454,6 @@ public static enum ENUM_PROPERTY_NAMING_TYPE {camelCase, PascalCase, snake_case, public static final String WAIT_TIME_OF_THREAD = "waitTimeMillis"; public static final String USE_DEFAULT_VALUES_FOR_REQUIRED_VARS = "useDefaultValuesForRequiredVars"; + + public static final String DEFAULT_TO_EMPTY_CONTAINER = "defaultToEmptyContainer"; } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index db2f6a563e91..e90ef5166988 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -88,6 +88,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import static org.openapitools.codegen.CodegenConstants.DEFAULT_TO_EMPTY_CONTAINER; import static org.openapitools.codegen.CodegenConstants.UNSUPPORTED_V310_SPEC_MSG; import static org.openapitools.codegen.utils.CamelizeOption.LOWERCASE_FIRST_LETTER; import static org.openapitools.codegen.utils.OnceLogger.once; @@ -338,7 +339,7 @@ apiTemplateFiles are for API outputs only (controllers/handlers). @Setter @Getter boolean arrayDefaultToEmpty, arrayNullableDefaultToEmpty, arrayOptionalNullableDefaultToEmpty, arrayOptionalDefaultToEmpty; @Setter @Getter boolean mapDefaultToEmpty, mapNullableDefaultToEmpty, mapOptionalNullableDefaultToEmpty, mapOptionalDefaultToEmpty; @Setter @Getter protected boolean defaultToEmptyContainer; - final String DEFAULT_TO_EMPTY_CONTAINER = "defaultToEmptyContainer"; + final List EMPTY_LIST = new ArrayList(); @Override @@ -4289,7 +4290,7 @@ void updateDefaultToEmptyContainer(CodegenProperty cp, Schema p) { } else { // required if (cp.isNullable && mapNullableDefaultToEmpty) { // nullable p.setDefault(EMPTY_LIST); - } else if (!cp.isNullable && mapOptionalDefaultToEmpty) { // non-nullable + } else if (!cp.isNullable && mapDefaultToEmpty) { // non-nullable p.setDefault(EMPTY_LIST); } } From 170442916551ce70ae1f13404f54b160d0d9a7bc Mon Sep 17 00:00:00 2001 From: Marco Date: Fri, 12 Sep 2025 07:31:47 +0200 Subject: [PATCH 2/3] Issue 21890: added test (first draft) --- .../codegen/java/AbstractJavaCodegenTest.java | 19 +++++-- .../test/resources/3_1/java/issue_21890.yaml | 57 +++++++++++++++++++ 2 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 modules/openapi-generator/src/test/resources/3_1/java/issue_21890.yaml diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/AbstractJavaCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/AbstractJavaCodegenTest.java index d0b39ffe9a35..7a26cf886073 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/AbstractJavaCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/AbstractJavaCodegenTest.java @@ -25,10 +25,7 @@ import io.swagger.v3.parser.core.models.ParseOptions; import org.mockito.Answers; import org.mockito.Mockito; -import org.openapitools.codegen.CodegenConstants; -import org.openapitools.codegen.CodegenModel; -import org.openapitools.codegen.CodegenParameter; -import org.openapitools.codegen.TestUtils; +import org.openapitools.codegen.*; import org.openapitools.codegen.languages.AbstractJavaCodegen; import org.openapitools.codegen.testutils.ConfigAssert; import org.openapitools.codegen.utils.ModelUtils; @@ -755,6 +752,20 @@ public void nullDefaultValueForModelWithDynamicProperties() { Assert.assertEquals(defaultValue, "null"); } + @Test + public void defaultEmptyListForModelWithAdditionalPropertyDefaultToEmptyContainer() { + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_1/java/issue_21890.yaml"); + codegen.additionalProperties().put(CodegenConstants.DEFAULT_TO_EMPTY_CONTAINER, "map"); + codegen.processOpts(); + codegen.setOpenAPI(openAPI); + + Schema schema = openAPI.getComponents().getSchemas().get("Pet_parents"); + + CodegenProperty parents = codegen.fromProperty("parents", schema, true); + String defaultValue = codegen.toDefaultValue(parents, schema); + Assert.assertEquals(defaultValue, "new HashMap()"); + } + @Test public void maplikeDefaultValueForModelWithStringToStringMapping() { final OpenAPI openAPI = FLATTENED_SPEC.get("3_0/mapSchemas"); diff --git a/modules/openapi-generator/src/test/resources/3_1/java/issue_21890.yaml b/modules/openapi-generator/src/test/resources/3_1/java/issue_21890.yaml new file mode 100644 index 000000000000..8442b94ea7a1 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_1/java/issue_21890.yaml @@ -0,0 +1,57 @@ +openapi: 3.1.0 +servers: + - url: 'http://petstore.swagger.io/v2' +info: + description: >- + This is a sample server Petstore server. For this sample, you can use the api key + `special-key` to test the authorization filters. + version: 1.0.0 + title: OpenAPI Petstore + license: + name: Apache-2.0 + url: 'https://www.apache.org/licenses/LICENSE-2.0.html' +paths: + '/pet/{petId}': + get: + tags: + - pet + summary: Find pet by ID + description: Returns a single pet + operationId: getPetById + parameters: + - name: petId + in: path + description: ID of pet to return + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid ID supplied + '404': + description: Pet not found +components: + schemas: + Pet: + title: a Pet + description: A pet for sale in the pet store + type: object + properties: + parents: + type: object + properties: + mother: + type: string + father: + type: string + required: + - parents + + From 4811da456def4aa13e00c0fb55595826e662d304 Mon Sep 17 00:00:00 2001 From: MarcoZurich Date: Fri, 12 Sep 2025 10:06:03 +0200 Subject: [PATCH 3/3] Issue 21890: Added Test --- .../codegen/java/AbstractJavaCodegenTest.java | 19 +++---------- .../java/spring/SpringCodegenTest.java | 24 +++++++++++++++++ .../{3_1 => 3_0}/java/issue_21890.yaml | 27 +++++++------------ 3 files changed, 37 insertions(+), 33 deletions(-) rename modules/openapi-generator/src/test/resources/{3_1 => 3_0}/java/issue_21890.yaml (67%) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/AbstractJavaCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/AbstractJavaCodegenTest.java index 7a26cf886073..d0b39ffe9a35 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/AbstractJavaCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/AbstractJavaCodegenTest.java @@ -25,7 +25,10 @@ import io.swagger.v3.parser.core.models.ParseOptions; import org.mockito.Answers; import org.mockito.Mockito; -import org.openapitools.codegen.*; +import org.openapitools.codegen.CodegenConstants; +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenParameter; +import org.openapitools.codegen.TestUtils; import org.openapitools.codegen.languages.AbstractJavaCodegen; import org.openapitools.codegen.testutils.ConfigAssert; import org.openapitools.codegen.utils.ModelUtils; @@ -752,20 +755,6 @@ public void nullDefaultValueForModelWithDynamicProperties() { Assert.assertEquals(defaultValue, "null"); } - @Test - public void defaultEmptyListForModelWithAdditionalPropertyDefaultToEmptyContainer() { - final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_1/java/issue_21890.yaml"); - codegen.additionalProperties().put(CodegenConstants.DEFAULT_TO_EMPTY_CONTAINER, "map"); - codegen.processOpts(); - codegen.setOpenAPI(openAPI); - - Schema schema = openAPI.getComponents().getSchemas().get("Pet_parents"); - - CodegenProperty parents = codegen.fromProperty("parents", schema, true); - String defaultValue = codegen.toDefaultValue(parents, schema); - Assert.assertEquals(defaultValue, "new HashMap()"); - } - @Test public void maplikeDefaultValueForModelWithStringToStringMapping() { final OpenAPI openAPI = FLATTENED_SPEC.get("3_0/mapSchemas"); diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java index 2af22ca3b5b8..be0e071381ac 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java @@ -5634,6 +5634,30 @@ public void testCollectionTypesWithDefaults_issue_collection() throws IOExceptio .fileContains("private List stringRequiredList = new ArrayList<>();"); } + @Test + public void testDefaultForRequiredNonNullableMap() throws IOException { + File output = Files.createTempDirectory("test").toFile().getCanonicalFile(); + output.deleteOnExit(); + + OpenAPI openAPI = new OpenAPIParser() + .readLocation("src/test/resources/3_0/java/issue_21890.yaml", null, new ParseOptions()).getOpenAPI(); + SpringCodegen codegen = new SpringCodegen(); + codegen.setLibrary(SPRING_BOOT); + codegen.setOutputDir(output.getAbsolutePath()); + codegen.additionalProperties().put("defaultToEmptyContainer", "map"); + + ClientOptInput input = new ClientOptInput() + .openAPI(openAPI) + .config(codegen); + + DefaultGenerator generator = new DefaultGenerator(); + Map files = generator.opts(input).generate().stream() + .collect(Collectors.toMap(File::getName, Function.identity())); + + JavaFileAssert.assertThat(files.get("Pet.java")) + .fileContains("private Map requiredNonNullableMap = new HashMap<>();"); + } + @Test public void testGenericReturnTypeWhenUsingResponseEntity_issue1096() throws IOException { Map additionalProperties = new HashMap<>(); diff --git a/modules/openapi-generator/src/test/resources/3_1/java/issue_21890.yaml b/modules/openapi-generator/src/test/resources/3_0/java/issue_21890.yaml similarity index 67% rename from modules/openapi-generator/src/test/resources/3_1/java/issue_21890.yaml rename to modules/openapi-generator/src/test/resources/3_0/java/issue_21890.yaml index 8442b94ea7a1..e43ac28f0105 100644 --- a/modules/openapi-generator/src/test/resources/3_1/java/issue_21890.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/java/issue_21890.yaml @@ -1,10 +1,9 @@ -openapi: 3.1.0 +openapi: 3.0.0 servers: - url: 'http://petstore.swagger.io/v2' info: description: >- - This is a sample server Petstore server. For this sample, you can use the api key - `special-key` to test the authorization filters. + This is a sample server Petstore server version: 1.0.0 title: OpenAPI Petstore license: @@ -33,25 +32,17 @@ paths: application/json: schema: $ref: '#/components/schemas/Pet' - '400': - description: Invalid ID supplied - '404': - description: Pet not found components: schemas: Pet: title: a Pet description: A pet for sale in the pet store type: object - properties: - parents: - type: object - properties: - mother: - type: string - father: - type: string required: - - parents - - + - requiredNonNullableMap + properties: + # Test for issue 21890. + # As this map is required and non-nullable, the generated java class should initialise this Map with new HashMap() + requiredNonNullableMap: + additionalProperties: + type: string