From b6ae8ea9e56c6b1e17ccfea398bafa6a12298b8d Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 7 Mar 2023 22:00:22 +0800 Subject: [PATCH 1/3] reorganize openapi normalizer tests --- .../codegen/DefaultCodegenTest.java | 180 ------------- .../codegen/OpenAPINormalizerTest.java | 239 ++++++++++++++++++ 2 files changed, 239 insertions(+), 180 deletions(-) create mode 100644 modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java index b393608b6261..cd4a82d15f00 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java @@ -4342,184 +4342,4 @@ public void testInlineEnumType() { Assert.assertFalse(inlineEnumSchemaProperty.isPrimitiveType); } - @Test - public void testOpenAPINormalizerRefAsParentInAllOf() { - // to test the rule REF_AS_PARENT_IN_ALLOF - OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/allOf_extension_parent.yaml"); - - Schema schema = openAPI.getComponents().getSchemas().get("AnotherPerson"); - assertNull(schema.getExtensions()); - - Schema schema2 = openAPI.getComponents().getSchemas().get("Person"); - assertEquals(schema2.getExtensions().get("x-parent"), "abstract"); - - Map options = new HashMap<>(); - options.put("REF_AS_PARENT_IN_ALLOF", "true"); - OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); - openAPINormalizer.normalize(); - - Schema schema3 = openAPI.getComponents().getSchemas().get("AnotherPerson"); - assertEquals(schema3.getExtensions().get("x-parent"), true); - - Schema schema4 = openAPI.getComponents().getSchemas().get("AnotherParent"); - assertEquals(schema4.getExtensions().get("x-parent"), true); - - Schema schema5 = openAPI.getComponents().getSchemas().get("Person"); - assertEquals(schema5.getExtensions().get("x-parent"), "abstract"); - } - - @Test - public void testOpenAPINormalizerEnableKeepOnlyFirstTagInOperation() { - OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/enableKeepOnlyFirstTagInOperation_test.yaml"); - - assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getTags().size(), 2); - assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getTags().size(), 1); - - Map options = new HashMap<>(); - options.put("KEEP_ONLY_FIRST_TAG_IN_OPERATION", "true"); - OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); - openAPINormalizer.normalize(); - - assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getTags().size(), 1); - assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getTags().size(), 1); - assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getTags().get(0), "person"); - } - - @Test - public void testOpenAPINormalizerRemoveAnyOfOneOfAndKeepPropertiesOnly() { - // to test the rule REMOVE_ANYOF_ONEOF_AND_KEEP_PROPERTIIES_ONLY - OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/removeAnyOfOneOfAndKeepPropertiesOnly_test.yaml"); - - Schema schema = openAPI.getComponents().getSchemas().get("Person"); - assertEquals(schema.getAnyOf().size(), 2); - - Map options = new HashMap<>(); - options.put("REMOVE_ANYOF_ONEOF_AND_KEEP_PROPERTIES_ONLY", "true"); - OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); - openAPINormalizer.normalize(); - - Schema schema3 = openAPI.getComponents().getSchemas().get("Person"); - assertNull(schema.getAnyOf()); - } - - @Test - public void testOpenAPINormalizerSimplifyOneOfAnyOfStringAndEnumString() { - // to test the rule SIMPLIFY_ONEOF_ANYOF_STRING_AND_ENUM_STRING - OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/simplifyAnyOfStringAndEnumString_test.yaml"); - - Schema schema = openAPI.getComponents().getSchemas().get("AnyOfTest"); - assertEquals(schema.getAnyOf().size(), 2); - - Map options = new HashMap<>(); - options.put("SIMPLIFY_ANYOF_STRING_AND_ENUM_STRING", "true"); - OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); - openAPINormalizer.normalize(); - - Schema schema3 = openAPI.getComponents().getSchemas().get("AnyOfTest"); - assertNull(schema3.getAnyOf()); - assertTrue(schema3 instanceof StringSchema); - } - - @Test - public void testOpenAPINormalizerSimplifyOneOfAnyOf() { - // to test the rule SIMPLIFY_ONEOF_ANYOF - OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/simplifyOneOfAnyOf_test.yaml"); - - Schema schema = openAPI.getComponents().getSchemas().get("AnyOfTest"); - assertEquals(schema.getAnyOf().size(), 2); - assertNull(schema.getNullable()); - - Schema schema2 = openAPI.getComponents().getSchemas().get("OneOfTest"); - assertEquals(schema2.getOneOf().size(), 2); - assertNull(schema2.getNullable()); - - Schema schema5 = openAPI.getComponents().getSchemas().get("OneOfNullableTest"); - assertEquals(schema5.getOneOf().size(), 3); - assertNull(schema5.getNullable()); - - Map options = new HashMap<>(); - options.put("SIMPLIFY_ONEOF_ANYOF", "true"); - OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); - openAPINormalizer.normalize(); - - Schema schema3 = openAPI.getComponents().getSchemas().get("AnyOfTest"); - assertNull(schema3.getAnyOf()); - assertTrue(schema3 instanceof StringSchema); - assertTrue(schema3.getNullable()); - - Schema schema4 = openAPI.getComponents().getSchemas().get("OneOfTest"); - assertNull(schema4.getOneOf()); - assertTrue(schema4 instanceof IntegerSchema); - - Schema schema6 = openAPI.getComponents().getSchemas().get("OneOfNullableTest"); - assertEquals(schema6.getOneOf().size(), 2); - assertTrue(schema6.getNullable()); - } - - @Test - public void testOpenAPINormalizerSimplifyBooleanEnum() { - // to test the rule SIMPLIFY_BOOLEAN_ENUM - OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/simplifyBooleanEnum_test.yaml"); - - Schema schema = openAPI.getComponents().getSchemas().get("BooleanEnumTest"); - assertEquals(schema.getProperties().size(), 3); - assertTrue(schema.getProperties().get("boolean_enum") instanceof BooleanSchema); - BooleanSchema bs = (BooleanSchema) schema.getProperties().get("boolean_enum"); - assertEquals(bs.getEnum().size(), 2); - - Map options = new HashMap<>(); - options.put("SIMPLIFY_BOOLEAN_ENUM", "true"); - OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); - openAPINormalizer.normalize(); - - Schema schema3 = openAPI.getComponents().getSchemas().get("BooleanEnumTest"); - assertEquals(schema.getProperties().size(), 3); - assertTrue(schema.getProperties().get("boolean_enum") instanceof BooleanSchema); - BooleanSchema bs2 = (BooleanSchema) schema.getProperties().get("boolean_enum"); - assertNull(bs2.getEnum()); //ensure the enum has been erased - } - - @Test - public void testOpenAPINormalizerSetTagsInAllOperations() { - OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/enableKeepOnlyFirstTagInOperation_test.yaml"); - - assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getTags().size(), 2); - assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getTags().size(), 1); - - Map options = new HashMap<>(); - options.put("SET_TAGS_FOR_ALL_OPERATIONS", "core"); - OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); - openAPINormalizer.normalize(); - - assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getTags().size(), 1); - assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getTags().size(), 1); - assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getTags().get(0), "core"); - assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getTags().get(0), "core"); - } - - @Test - public void testAddUnsignedToIntegerWithInvalidMaxValue() { - OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/addUnsignedToIntegerWithInvalidMaxValue_test.yaml"); - - Schema person = openAPI.getComponents().getSchemas().get("Person"); - assertNull(((Schema)person.getProperties().get("integer")).getExtensions()); - assertNull(((Schema)person.getProperties().get("int32")).getExtensions()); - assertNull(((Schema)person.getProperties().get("int64")).getExtensions()); - assertNull(((Schema)person.getProperties().get("integer_max")).getExtensions()); - assertNull(((Schema)person.getProperties().get("int32_max")).getExtensions()); - assertNull(((Schema)person.getProperties().get("int64_max")).getExtensions()); - - Map options = new HashMap<>(); - options.put("ADD_UNSIGNED_TO_INTEGER_WITH_INVALID_MAX_VALUE", "true"); - OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); - openAPINormalizer.normalize(); - - Schema person2 = openAPI.getComponents().getSchemas().get("Person"); - assertNull(((Schema)person2.getProperties().get("integer")).getExtensions()); - assertNull(((Schema)person2.getProperties().get("int32")).getExtensions()); - assertNull(((Schema)person2.getProperties().get("int64")).getExtensions()); - assertTrue((Boolean)((Schema)person2.getProperties().get("integer_max")).getExtensions().get("x-unsigned")); - assertTrue((Boolean)((Schema)person2.getProperties().get("int32_max")).getExtensions().get("x-unsigned")); - assertTrue((Boolean)((Schema)person2.getProperties().get("int64_max")).getExtensions().get("x-unsigned")); - } } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java new file mode 100644 index 000000000000..06f8a82d023e --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java @@ -0,0 +1,239 @@ +/* + * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openapitools.codegen; + +import com.google.common.collect.Sets; +import com.samskivert.mustache.Mustache.Lambda; + +import io.swagger.parser.OpenAPIParser; +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; +import io.swagger.v3.oas.models.headers.Header; +import io.swagger.v3.oas.models.media.*; +import io.swagger.v3.oas.models.parameters.QueryParameter; +import io.swagger.v3.oas.models.parameters.RequestBody; +import io.swagger.v3.oas.models.responses.ApiResponse; +import io.swagger.v3.oas.models.responses.ApiResponses; +import io.swagger.v3.oas.models.security.SecurityScheme; +import io.swagger.v3.parser.core.models.ParseOptions; + +import org.openapitools.codegen.config.CodegenConfigurator; +import org.openapitools.codegen.config.GlobalSettings; +import org.openapitools.codegen.model.ModelMap; +import org.openapitools.codegen.model.ModelsMap; +import org.openapitools.codegen.templating.mustache.CamelCaseLambda; +import org.openapitools.codegen.templating.mustache.IndentedLambda; +import org.openapitools.codegen.templating.mustache.LowercaseLambda; +import org.openapitools.codegen.templating.mustache.TitlecaseLambda; +import org.openapitools.codegen.templating.mustache.UppercaseLambda; +import org.openapitools.codegen.utils.ModelUtils; +import org.openapitools.codegen.utils.SemVer; +import org.testng.Assert; +import org.testng.annotations.Ignore; +import org.testng.annotations.Test; + +import java.io.File; +import java.nio.file.Files; +import java.util.*; +import java.util.stream.Collectors; + +import static org.testng.Assert.*; + +public class OpenAPINormalizerTest { + @Test + public void testOpenAPINormalizerRefAsParentInAllOf() { + // to test the rule REF_AS_PARENT_IN_ALLOF + OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/allOf_extension_parent.yaml"); + + Schema schema = openAPI.getComponents().getSchemas().get("AnotherPerson"); + assertNull(schema.getExtensions()); + + Schema schema2 = openAPI.getComponents().getSchemas().get("Person"); + assertEquals(schema2.getExtensions().get("x-parent"), "abstract"); + + Map options = new HashMap<>(); + options.put("REF_AS_PARENT_IN_ALLOF", "true"); + OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); + openAPINormalizer.normalize(); + + Schema schema3 = openAPI.getComponents().getSchemas().get("AnotherPerson"); + assertEquals(schema3.getExtensions().get("x-parent"), true); + + Schema schema4 = openAPI.getComponents().getSchemas().get("AnotherParent"); + assertEquals(schema4.getExtensions().get("x-parent"), true); + + Schema schema5 = openAPI.getComponents().getSchemas().get("Person"); + assertEquals(schema5.getExtensions().get("x-parent"), "abstract"); + } + + @Test + public void testOpenAPINormalizerEnableKeepOnlyFirstTagInOperation() { + OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/enableKeepOnlyFirstTagInOperation_test.yaml"); + + assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getTags().size(), 2); + assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getTags().size(), 1); + + Map options = new HashMap<>(); + options.put("KEEP_ONLY_FIRST_TAG_IN_OPERATION", "true"); + OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); + openAPINormalizer.normalize(); + + assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getTags().size(), 1); + assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getTags().size(), 1); + assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getTags().get(0), "person"); + } + + @Test + public void testOpenAPINormalizerRemoveAnyOfOneOfAndKeepPropertiesOnly() { + // to test the rule REMOVE_ANYOF_ONEOF_AND_KEEP_PROPERTIIES_ONLY + OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/removeAnyOfOneOfAndKeepPropertiesOnly_test.yaml"); + + Schema schema = openAPI.getComponents().getSchemas().get("Person"); + assertEquals(schema.getAnyOf().size(), 2); + + Map options = new HashMap<>(); + options.put("REMOVE_ANYOF_ONEOF_AND_KEEP_PROPERTIES_ONLY", "true"); + OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); + openAPINormalizer.normalize(); + + Schema schema3 = openAPI.getComponents().getSchemas().get("Person"); + assertNull(schema.getAnyOf()); + } + + @Test + public void testOpenAPINormalizerSimplifyOneOfAnyOfStringAndEnumString() { + // to test the rule SIMPLIFY_ONEOF_ANYOF_STRING_AND_ENUM_STRING + OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/simplifyAnyOfStringAndEnumString_test.yaml"); + + Schema schema = openAPI.getComponents().getSchemas().get("AnyOfTest"); + assertEquals(schema.getAnyOf().size(), 2); + + Map options = new HashMap<>(); + options.put("SIMPLIFY_ANYOF_STRING_AND_ENUM_STRING", "true"); + OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); + openAPINormalizer.normalize(); + + Schema schema3 = openAPI.getComponents().getSchemas().get("AnyOfTest"); + assertNull(schema3.getAnyOf()); + assertTrue(schema3 instanceof StringSchema); + } + + @Test + public void testOpenAPINormalizerSimplifyOneOfAnyOf() { + // to test the rule SIMPLIFY_ONEOF_ANYOF + OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/simplifyOneOfAnyOf_test.yaml"); + + Schema schema = openAPI.getComponents().getSchemas().get("AnyOfTest"); + assertEquals(schema.getAnyOf().size(), 2); + assertNull(schema.getNullable()); + + Schema schema2 = openAPI.getComponents().getSchemas().get("OneOfTest"); + assertEquals(schema2.getOneOf().size(), 2); + assertNull(schema2.getNullable()); + + Schema schema5 = openAPI.getComponents().getSchemas().get("OneOfNullableTest"); + assertEquals(schema5.getOneOf().size(), 3); + assertNull(schema5.getNullable()); + + Map options = new HashMap<>(); + options.put("SIMPLIFY_ONEOF_ANYOF", "true"); + OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); + openAPINormalizer.normalize(); + + Schema schema3 = openAPI.getComponents().getSchemas().get("AnyOfTest"); + assertNull(schema3.getAnyOf()); + assertTrue(schema3 instanceof StringSchema); + assertTrue(schema3.getNullable()); + + Schema schema4 = openAPI.getComponents().getSchemas().get("OneOfTest"); + assertNull(schema4.getOneOf()); + assertTrue(schema4 instanceof IntegerSchema); + + Schema schema6 = openAPI.getComponents().getSchemas().get("OneOfNullableTest"); + assertEquals(schema6.getOneOf().size(), 2); + assertTrue(schema6.getNullable()); + } + + @Test + public void testOpenAPINormalizerSimplifyBooleanEnum() { + // to test the rule SIMPLIFY_BOOLEAN_ENUM + OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/simplifyBooleanEnum_test.yaml"); + + Schema schema = openAPI.getComponents().getSchemas().get("BooleanEnumTest"); + assertEquals(schema.getProperties().size(), 3); + assertTrue(schema.getProperties().get("boolean_enum") instanceof BooleanSchema); + BooleanSchema bs = (BooleanSchema) schema.getProperties().get("boolean_enum"); + assertEquals(bs.getEnum().size(), 2); + + Map options = new HashMap<>(); + options.put("SIMPLIFY_BOOLEAN_ENUM", "true"); + OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); + openAPINormalizer.normalize(); + + Schema schema3 = openAPI.getComponents().getSchemas().get("BooleanEnumTest"); + assertEquals(schema.getProperties().size(), 3); + assertTrue(schema.getProperties().get("boolean_enum") instanceof BooleanSchema); + BooleanSchema bs2 = (BooleanSchema) schema.getProperties().get("boolean_enum"); + assertNull(bs2.getEnum()); //ensure the enum has been erased + } + + @Test + public void testOpenAPINormalizerSetTagsInAllOperations() { + OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/enableKeepOnlyFirstTagInOperation_test.yaml"); + + assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getTags().size(), 2); + assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getTags().size(), 1); + + Map options = new HashMap<>(); + options.put("SET_TAGS_FOR_ALL_OPERATIONS", "core"); + OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); + openAPINormalizer.normalize(); + + assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getTags().size(), 1); + assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getTags().size(), 1); + assertEquals(openAPI.getPaths().get("/person/display/{personId}").getGet().getTags().get(0), "core"); + assertEquals(openAPI.getPaths().get("/person/display/{personId}").getDelete().getTags().get(0), "core"); + } + + @Test + public void testAddUnsignedToIntegerWithInvalidMaxValue() { + OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/addUnsignedToIntegerWithInvalidMaxValue_test.yaml"); + + Schema person = openAPI.getComponents().getSchemas().get("Person"); + assertNull(((Schema)person.getProperties().get("integer")).getExtensions()); + assertNull(((Schema)person.getProperties().get("int32")).getExtensions()); + assertNull(((Schema)person.getProperties().get("int64")).getExtensions()); + assertNull(((Schema)person.getProperties().get("integer_max")).getExtensions()); + assertNull(((Schema)person.getProperties().get("int32_max")).getExtensions()); + assertNull(((Schema)person.getProperties().get("int64_max")).getExtensions()); + + Map options = new HashMap<>(); + options.put("ADD_UNSIGNED_TO_INTEGER_WITH_INVALID_MAX_VALUE", "true"); + OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); + openAPINormalizer.normalize(); + + Schema person2 = openAPI.getComponents().getSchemas().get("Person"); + assertNull(((Schema)person2.getProperties().get("integer")).getExtensions()); + assertNull(((Schema)person2.getProperties().get("int32")).getExtensions()); + assertNull(((Schema)person2.getProperties().get("int64")).getExtensions()); + assertTrue((Boolean)((Schema)person2.getProperties().get("integer_max")).getExtensions().get("x-unsigned")); + assertTrue((Boolean)((Schema)person2.getProperties().get("int32_max")).getExtensions().get("x-unsigned")); + assertTrue((Boolean)((Schema)person2.getProperties().get("int64_max")).getExtensions().get("x-unsigned")); + } +} From 3f2ddd1573f7c9bd3c4023d209b1a9a1b21ed017 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 8 Mar 2023 10:30:58 +0800 Subject: [PATCH 2/3] add the logic to simply oneof anyof rule instead --- docs/customization.md | 2 +- .../codegen/OpenAPINormalizer.java | 16 ++++++- .../codegen/OpenAPINormalizerTest.java | 19 ++++++++ .../3_0/convertEnumNullToNullable_test.yaml | 43 +++++++++++++++++++ 4 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 modules/openapi-generator/src/test/resources/3_0/convertEnumNullToNullable_test.yaml diff --git a/docs/customization.md b/docs/customization.md index 90676792631c..d8ff7fb07465 100644 --- a/docs/customization.md +++ b/docs/customization.md @@ -485,7 +485,7 @@ Example: java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_0/simplifyBooleanEnum_test.yaml -o /tmp/java-okhttp/ --openapi-normalizer SIMPLIFY_BOOLEAN_ENUM=true ``` -- `SIMPLIFY_ONEOF_ANYOF`: when set to `true`, simplify oneOf/anyOf by 1) removing null (sub-schema) and setting nullable to true instead, and 2) simplifying oneOf/anyOf with a single sub-schema to just the sub-schema itself. +- `SIMPLIFY_ONEOF_ANYOF`: when set to `true`, simplify oneOf/anyOf by 1) removing null (sub-schema) or enum of null (sub-schema) and setting nullable to true instead, and 2) simplifying oneOf/anyOf with a single sub-schema to just the sub-schema itself. Example: ``` diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java index c11f296d2373..911e2c697e75 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java @@ -65,6 +65,7 @@ public class OpenAPINormalizer { // when set to true, oneOf/anyOf schema with only one sub-schema is simplified to just the sub-schema // and if sub-schema contains "null", remove it and set nullable to true instead + // and if sub-schema contains enum of "null", remove it and set nullable to true instead final String SIMPLIFY_ONEOF_ANYOF = "SIMPLIFY_ONEOF_ANYOF"; boolean simplifyOneOfAnyOf; @@ -649,11 +650,22 @@ private Schema processSimplifyAnyOf(Schema schema) { } if (schema.getAnyOf() != null && !schema.getAnyOf().isEmpty()) { - // convert null sub-schema to `nullable: true` for (int i = 0; i < schema.getAnyOf().size(); i++) { + // convert null sub-schema to `nullable: true` if (schema.getAnyOf().get(i) == null || ((Schema) schema.getAnyOf().get(i)).getType() == null) { schema.getAnyOf().remove(i); schema.setNullable(true); + continue; + } + + // convert enum of null only to `nullable:true` + Schema anyOfElement = ModelUtils.getReferencedSchema(openAPI, (Schema) schema.getAnyOf().get(i)); + if (anyOfElement.getEnum() != null && anyOfElement.getEnum().size() == 1) { + if ("null".equals(String.valueOf(anyOfElement.getEnum().get(0)))) { + schema.setNullable(true); + schema.getAnyOf().remove(i); + continue; + } } } @@ -721,4 +733,4 @@ private void processAddUnsignedToIntegerWithInvalidMaxValue(Schema schema) { } // ===================== end of rules ===================== -} +} \ No newline at end of file diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java index 06f8a82d023e..a5b80494f621 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java @@ -236,4 +236,23 @@ public void testAddUnsignedToIntegerWithInvalidMaxValue() { assertTrue((Boolean)((Schema)person2.getProperties().get("int32_max")).getExtensions().get("x-unsigned")); assertTrue((Boolean)((Schema)person2.getProperties().get("int64_max")).getExtensions().get("x-unsigned")); } + + @Test + public void testOpenAPINormalizerConvertEnumNullToNullable_test() { + // to test the rule SIMPLIFY_ONEOF_ANYOF, which now also covers CONVERT_ENUM_NULL_TO_NULLABLE (removed) + OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/convertEnumNullToNullable_test.yaml"); + + Schema schema = openAPI.getComponents().getSchemas().get("AnyOfTest"); + assertEquals(schema.getAnyOf().size(), 3); + assertNull(schema.getNullable()); + + Map options = new HashMap<>(); + options.put("SIMPLIFY_ONEOF_ANYOF", "true"); + OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); + openAPINormalizer.normalize(); + + Schema schema3 = openAPI.getComponents().getSchemas().get("AnyOfTest"); + assertEquals(schema3.getAnyOf().size(), 2); + assertTrue(schema3.getNullable()); + } } diff --git a/modules/openapi-generator/src/test/resources/3_0/convertEnumNullToNullable_test.yaml b/modules/openapi-generator/src/test/resources/3_0/convertEnumNullToNullable_test.yaml new file mode 100644 index 000000000000..ab97e13abbdb --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/convertEnumNullToNullable_test.yaml @@ -0,0 +1,43 @@ +openapi: 3.0.1 +info: + version: 1.0.0 + title: Example + license: + name: MIT +servers: + - url: http://api.example.xyz/v1 +paths: + /person/display/{personId}: + get: + parameters: + - name: personId + in: path + required: true + description: The id of the person to retrieve + schema: + type: string + operationId: list + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/AnyOfTest" +components: + schemas: + AnyOfTest: + description: to test anyOf (string, enum string) + anyOf: + - type: string + - $ref: '#/components/schemas/EnumString' + - $ref: '#/components/schemas/EnumNull' + EnumString: + type: string + enum: + - A + - B + EnumNull: + type: string + enum: + - null From e55becf12a51c113ff1f1cf7d225b6fe70d1b958 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 8 Mar 2023 19:15:52 +0800 Subject: [PATCH 3/3] minor fix --- .../codegen/OpenAPINormalizer.java | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java index 911e2c697e75..49d1d714a040 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java @@ -579,7 +579,7 @@ private Schema processSimplifyAnyOfStringAndEnumString(Schema schema) { return schema; } - Schema s0 = null, s1 = null; + Schema result = null, s0 = null, s1 = null; if (schema.getAnyOf().size() == 2) { s0 = ModelUtils.unaliasSchema(openAPI, (Schema) schema.getAnyOf().get(0)); s1 = ModelUtils.unaliasSchema(openAPI, (Schema) schema.getAnyOf().get(1)); @@ -593,15 +593,27 @@ private Schema processSimplifyAnyOfStringAndEnumString(Schema schema) { // find the string schema (not enum) if (s0 instanceof StringSchema && s1 instanceof StringSchema) { if (((StringSchema) s0).getEnum() != null) { // s0 is enum, s1 is string - return (StringSchema) s1; + result = (StringSchema) s1; } else if (((StringSchema) s1).getEnum() != null) { // s1 is enum, s0 is string - return (StringSchema) s0; + result = (StringSchema) s0; } else { // both are string - return schema; + result = schema; } } else { - return schema; + result = schema; + } + + // set nullable + if (schema.getNullable() != null) { + result.setNullable(schema.getNullable()); } + + // set default + if (schema.getDefault() != null) { + result.setDefault(schema.getDefault()); + } + + return result; } /** @@ -617,11 +629,22 @@ private Schema processSimplifyOneOf(Schema schema) { } if (schema.getOneOf() != null && !schema.getOneOf().isEmpty()) { - // convert null sub-schema to `nullable: true` for (int i = 0; i < schema.getOneOf().size(); i++) { + // convert null sub-schema to `nullable: true` if (schema.getOneOf().get(i) == null || ((Schema) schema.getOneOf().get(i)).getType() == null) { schema.getOneOf().remove(i); schema.setNullable(true); + continue; + } + + // convert enum of null only to `nullable:true` + Schema oneOfElement = ModelUtils.getReferencedSchema(openAPI, (Schema) schema.getOneOf().get(i)); + if (oneOfElement.getEnum() != null && oneOfElement.getEnum().size() == 1) { + if ("null".equals(String.valueOf(oneOfElement.getEnum().get(0)))) { + schema.setNullable(true); + schema.getOneOf().remove(i); + continue; + } } }