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 94eb3273c049..c379903b16c9 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 @@ -7804,8 +7804,15 @@ protected void updateRequestBodyForArray(CodegenParameter codegenParameter, Sche } } - protected void updateRequestBodyForString(CodegenParameter codegenParameter, Schema schema, Set imports, String bodyParameterName) { - updateRequestBodyForPrimitiveType(codegenParameter, schema, bodyParameterName, imports); + protected void updateRequestBodyForString(CodegenParameter codegenParameter, Schema schema, String name, Set imports, String bodyParameterName) { + // when a name is present, it means that the schema has a $ref to a schema defined under /components/schemas + // in the OAS document + if (!StringUtils.isEmpty(name)) { + addBodyModelSchema(codegenParameter, name, schema, imports, bodyParameterName, false); + } else { + updateRequestBodyForPrimitiveType(codegenParameter, schema, bodyParameterName, imports); + } + if (ModelUtils.isByteArraySchema(schema)) { codegenParameter.setIsString(false); codegenParameter.isByteArray = true; @@ -8006,7 +8013,7 @@ public CodegenParameter fromRequestBody(RequestBody body, Set imports, S // swagger v2 only, type file codegenParameter.isFile = true; } else if (ModelUtils.isStringSchema(schema)) { - updateRequestBodyForString(codegenParameter, schema, imports, bodyParameterName); + updateRequestBodyForString(codegenParameter, schema, name, imports, bodyParameterName); } else if (ModelUtils.isNumberSchema(schema)) { updateRequestBodyForPrimitiveType(codegenParameter, schema, bodyParameterName, imports); codegenParameter.isNumeric = Boolean.TRUE; 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 f1aca92f0c05..3f65cc0ba0e1 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 @@ -30,7 +30,16 @@ 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.media.ArraySchema; +import io.swagger.v3.oas.models.media.Content; +import io.swagger.v3.oas.models.media.Encoding; +import io.swagger.v3.oas.models.media.IntegerSchema; +import io.swagger.v3.oas.models.media.MapSchema; +import io.swagger.v3.oas.models.media.MediaType; +import io.swagger.v3.oas.models.media.NumberSchema; +import io.swagger.v3.oas.models.media.ObjectSchema; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.media.StringSchema; import io.swagger.v3.oas.models.parameters.QueryParameter; import io.swagger.v3.oas.models.parameters.RequestBody; import io.swagger.v3.oas.models.responses.ApiResponse; @@ -43,7 +52,11 @@ import org.openapitools.codegen.languages.SpringCodegen; import org.openapitools.codegen.model.ModelMap; import org.openapitools.codegen.model.ModelsMap; -import org.openapitools.codegen.templating.mustache.*; +import org.openapitools.codegen.templating.mustache.CamelCaseAndSanitizeLambda; +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.slf4j.LoggerFactory; @@ -52,13 +65,35 @@ import org.testng.annotations.Test; import java.io.File; +import java.io.IOException; import java.nio.file.Files; -import java.util.*; -import java.util.concurrent.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; public class DefaultCodegenTest { @@ -5057,4 +5092,72 @@ private List getNames(List props) { if (props == null) return null; return props.stream().map(v -> v.name).collect(Collectors.toList()); } + + @Test + public void testRequestBodyWith$RefToEnumSchema() { + // Given + OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_1/issue_21407.yaml"); + DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + String path = "/v1/resource-class/send-with-$ref-to-enum-schema"; + + // When + CodegenOperation codegenOperation = codegen.fromOperation(path, "POST", openAPI.getPaths().get(path).getPost(), null); + + // Then + assertThat(codegenOperation.bodyParam).satisfies(bodyParam -> { + assertThat(bodyParam).isNotNull(); + assertThat(bodyParam.getDataType()).isEqualTo("Letter"); + }); + } + + @Test + public void testRequestBodyWithInlineEnumSchema() throws IOException { + // Given + OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_1/issue_21407.yaml"); + File outputDir = Files.createTempDirectory("test").toFile(); + + CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("java") + .setInputSpec("src/test/resources/3_1/issue_21407.yaml") + .addInlineSchemaOption("RESOLVE_INLINE_ENUMS", "true") + .setOutputDir(outputDir.getAbsolutePath()); + + ClientOptInput clientOptInput = configurator.toClientOptInput(); + clientOptInput.openAPI(openAPI); + + DefaultGenerator generator = new DefaultGenerator(); + generator.opts(clientOptInput).generate(); + + String path = "/v1/resource-class/send-with-inline-enum-schema"; + + // When + CodegenOperation codegenOperation = generator.config.fromOperation(path, "POST", openAPI.getPaths().get(path).getPost(), null); + + // Then + assertThat(codegenOperation.bodyParam).satisfies(bodyParam -> { + assertThat(bodyParam).isNotNull(); + // expecting a type that is different from String + assertThat(bodyParam.getDataType()).isEqualTo("SendWithInlineEnumSchemaRequest"); + }); + } + + @Test + public void testRequestBodyWithStringType() { + // Given + OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_1/issue_21407.yaml"); + DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + String path = "/v1/resource-class/send-with-string"; + + // When + CodegenOperation codegenOperation = codegen.fromOperation(path, "POST", openAPI.getPaths().get(path).getPost(), null); + + // Then + assertThat(codegenOperation.bodyParam).satisfies(bodyParam -> { + assertThat(bodyParam).isNotNull(); + assertThat(bodyParam.getDataType()).isEqualTo("String"); + }); + } + } diff --git a/modules/openapi-generator/src/test/resources/3_1/issue_21407.yaml b/modules/openapi-generator/src/test/resources/3_1/issue_21407.yaml new file mode 100644 index 000000000000..011a39774282 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_1/issue_21407.yaml @@ -0,0 +1,65 @@ +openapi: 3.1.0 +info: + title: sample spec + description: "Sample spec" + version: 0.0.1 +tags: +- name: ResourceClass +paths: + /v1/resource-class/send-with-$ref-to-enum-schema: + post: + tags: + - ResourceClass + description: Add @Operation annotation to provide a description + operationId: send-with-$ref-to-enum-schema + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/Letter" + responses: + "200": + description: OK - the request has succeeded. + content: + application/json: + schema: + $ref: "#/components/schemas/Letter" + /v1/resource-class/send-with-string: + post: + tags: + - ResourceClass + description: Add @Operation annotation to provide a description + operationId: send-with-string + requestBody: + content: + application/json: + schema: + type: string + responses: + "204": + description: "No Content - the request has been successfully processed,\ + \ but there is no additional content." + /v1/resource-class/send-with-inline-enum-schema: + post: + tags: + - ResourceClass + description: Add @Operation annotation to provide a description + operationId: send-with-inline-enum-schema + requestBody: + content: + application/json: + schema: + type: string + enum: + - B + responses: + "204": + description: "No Content - the request has been successfully processed,\ + \ but there is no additional content." +components: + schemas: + Letter: + type: string + enum: + - A +jsonSchemaDialect: https://spec.openapis.org/oas/3.1/dialect/base