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 b42858a24945..8b987c863a1b 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 @@ -915,6 +915,11 @@ public String toEnumVarName(String value, String datatype) { } public boolean specVersionGreaterThanOrEqualTo310(OpenAPI openAPI) { + String originalSpecVersion = getOriginalSpecVersion(openAPI); + return getMajorSpecVersion(originalSpecVersion) == 3 && getMinorSpecVersion(originalSpecVersion) >= 1; + } + + private String getOriginalSpecVersion(OpenAPI openAPI) { String originalSpecVersion; String xOriginalSwaggerVersion = "x-original-swagger-version"; if (openAPI.getExtensions() != null && !openAPI.getExtensions().isEmpty() && openAPI.getExtensions().containsValue(xOriginalSwaggerVersion)) { @@ -922,9 +927,15 @@ public boolean specVersionGreaterThanOrEqualTo310(OpenAPI openAPI) { } else { originalSpecVersion = openAPI.getOpenapi(); } - Integer specMajorVersion = Integer.parseInt(originalSpecVersion.substring(0, 1)); - Integer specMinorVersion = Integer.parseInt(originalSpecVersion.substring(2, 3)); - return specMajorVersion == 3 && specMinorVersion >= 1; + return originalSpecVersion; + } + + private Integer getMajorSpecVersion(String originalSpecVersion) { + return Integer.parseInt(originalSpecVersion.substring(0, 1)); + } + + private Integer getMinorSpecVersion(String originalSpecVersion) { + return Integer.parseInt(originalSpecVersion.substring(2, 3)); } /** @@ -5201,16 +5212,22 @@ public CodegenParameter fromParameter(Parameter parameter, Set imports) parameterSchema = null; } + String defaultV3Style = null; + if (parameter instanceof QueryParameter || "query".equalsIgnoreCase(parameter.getIn())) { codegenParameter.isQueryParam = true; codegenParameter.isAllowEmptyValue = parameter.getAllowEmptyValue() != null && parameter.getAllowEmptyValue(); + defaultV3Style = Parameter.StyleEnum.FORM.toString(); } else if (parameter instanceof PathParameter || "path".equalsIgnoreCase(parameter.getIn())) { codegenParameter.required = true; codegenParameter.isPathParam = true; + defaultV3Style = Parameter.StyleEnum.SIMPLE.toString(); } else if (parameter instanceof HeaderParameter || "header".equalsIgnoreCase(parameter.getIn())) { codegenParameter.isHeaderParam = true; + defaultV3Style = Parameter.StyleEnum.SIMPLE.toString(); } else if (parameter instanceof CookieParameter || "cookie".equalsIgnoreCase(parameter.getIn())) { codegenParameter.isCookieParam = true; + defaultV3Style = Parameter.StyleEnum.FORM.toString(); } else { LOGGER.warn("Unknown parameter type: {}", parameter.getName()); } @@ -5247,11 +5264,15 @@ public CodegenParameter fromParameter(Parameter parameter, Set imports) codegenParameter.style = parameter.getStyle().toString(); codegenParameter.isDeepObject = Parameter.StyleEnum.DEEPOBJECT == parameter.getStyle(); codegenParameter.isMatrix = Parameter.StyleEnum.MATRIX == parameter.getStyle(); + } else if (openAPI != null && getMajorSpecVersion(getOriginalSpecVersion(openAPI)) >= 3) { + // Properly sets the default style for oas V3 + codegenParameter.style = defaultV3Style; } - // the default value is false + // the default value is true if style is set to form, false otherwise // https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#user-content-parameterexplode - codegenParameter.isExplode = parameter.getExplode() != null && parameter.getExplode(); + boolean isFormStyle = Parameter.StyleEnum.FORM.toString().equals(codegenParameter.style); + codegenParameter.isExplode = parameter.getExplode() != null ? parameter.getExplode() : isFormStyle; // TODO revise collectionFormat, default collection format in OAS 3 appears to multi at least for query parameters // https://swagger.io/docs/specification/serialization/ @@ -7105,18 +7126,23 @@ public static Set getProducesInfo(final OpenAPI openAPI, final Operation } protected String getCollectionFormat(Parameter parameter) { - if (Parameter.StyleEnum.FORM.equals(parameter.getStyle())) { + String style = parameter.getStyle() != null ? parameter.getStyle().toString() : null; + return getCollectionFormat(style, parameter.getExplode()); + } + + private String getCollectionFormat(String style, Boolean explode) { + if (Parameter.StyleEnum.FORM.toString().equals(style)) { // Ref: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#style-values - if (Boolean.TRUE.equals(parameter.getExplode())) { // explode is true (default) + if (Boolean.TRUE.equals(explode)) { // explode is true (default) return "multi"; } else { return "csv"; } - } else if (Parameter.StyleEnum.SIMPLE.equals(parameter.getStyle())) { + } else if (Parameter.StyleEnum.SIMPLE.toString().equals(style)) { return "csv"; - } else if (Parameter.StyleEnum.PIPEDELIMITED.equals(parameter.getStyle())) { + } else if (Parameter.StyleEnum.PIPEDELIMITED.toString().equals(style)) { return "pipes"; - } else if (Parameter.StyleEnum.SPACEDELIMITED.equals(parameter.getStyle())) { + } else if (Parameter.StyleEnum.SPACEDELIMITED.toString().equals(style)) { return "ssv"; } else { return null; @@ -8424,23 +8450,7 @@ protected static boolean isJsonVendorMimeType(String mime) { * @return string for a collectionFormat. */ protected String getCollectionFormat(CodegenParameter codegenParameter) { - if ("form".equals(codegenParameter.style)) { - // Ref: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#style-values - if (codegenParameter.isExplode) { - return "multi"; - } else { - return "csv"; - } - } else if ("simple".equals(codegenParameter.style)) { - return "csv"; - } else if ("pipeDelimited".equals(codegenParameter.style)) { - return "pipes"; - } else if ("spaceDelimited".equals(codegenParameter.style)) { - return "ssv"; - } else { - // Doesn't map to any of the collectionFormat strings - return null; - } + return getCollectionFormat(codegenParameter.style, codegenParameter.isExplode); } private CodegenComposedSchemas getComposedSchemas(Schema schema) { diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java index 6789b897591a..1fb7f6b4d3ac 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java @@ -1912,6 +1912,22 @@ public void shouldProperlyExplodeRestTemplateQueryParameters_issue907() { + " objectParam.getSomeInteger()));"); } + @Test + public void shouldProperlyExplodeRestTemplateArrayQueryParameters_issue20127() { + final Map files = generateFromContract( + "src/test/resources/3_0/exploded-query-param-array.yaml", + RESTTEMPLATE + ); + + JavaFileAssert.assertThat(files.get("DefaultApi.java")) + .printFileContent() + .assertMethod("getSomeValueWithHttpInfo") + .bodyContainsLines( + "localVarQueryParams.putAll(apiClient.parameterToMultiValueMap(" + + "ApiClient.CollectionFormat.valueOf(\"multi\".toUpperCase(Locale.ROOT))," + + " \"QueryArray\", queryArray));"); + } + @Test public void shouldProperlyExplodeWebClientQueryParameters() { final Map files = generateFromContract( @@ -1936,6 +1952,22 @@ public void shouldProperlyExplodeWebClientQueryParameters() { + " objectParam.getSomeInteger()));"); } + @Test + public void shouldProperlyExplodeWebClientArrayQueryParameters_issue20127() { + final Map files = generateFromContract( + "src/test/resources/3_0/exploded-query-param-array.yaml", + JavaClientCodegen.WEBCLIENT + ); + + JavaFileAssert.assertThat(files.get("DefaultApi.java")) + .printFileContent() + .assertMethod("getSomeValueRequestCreation") + .bodyContainsLines( + "queryParams.putAll(apiClient.parameterToMultiValueMap(" + + "ApiClient.CollectionFormat.valueOf(\"multi\".toUpperCase(Locale.ROOT))," + + " \"QueryArray\", queryArray));"); + } + private static Map generateFromContract(final String pathToSpecification, final String library) { return generateFromContract(pathToSpecification, library, new HashMap<>()); } diff --git a/modules/openapi-generator/src/test/resources/3_0/exploded-query-param-array.yaml b/modules/openapi-generator/src/test/resources/3_0/exploded-query-param-array.yaml index a46d6b753e08..5c064b0476d8 100644 --- a/modules/openapi-generator/src/test/resources/3_0/exploded-query-param-array.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/exploded-query-param-array.yaml @@ -21,6 +21,12 @@ paths: type: array items: type: string + - name: QueryArray + in: query + schema: + type: array + items: + type: string responses: '200': description: Some return value