diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java index a94d4d7ff025..0dee6e7ec8d7 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java @@ -1749,10 +1749,14 @@ private String getDefaultCollectionType(String arrayFormat, String defaultValues @Override public String toDefaultParameterValue(final Schema schema) { - Object defaultValue = schema.get$ref() != null ? ModelUtils.getReferencedSchema(openAPI, schema).getDefault() : schema.getDefault(); + Schema referencedSchema = schema.get$ref() != null ? ModelUtils.getReferencedSchema(openAPI, schema) : schema; + Object defaultValue = schema.getDefault() != null ? schema.getDefault() : referencedSchema.getDefault(); if (defaultValue == null) { return null; } + if (isNullNode(defaultValue)) { + return null; + } if (defaultValue instanceof Date) { Date date = (Date) schema.getDefault(); LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); 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 144bb6927b96..398850ed9b5b 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 @@ -3029,6 +3029,58 @@ public void shouldIgnorePageableForSpringHttpInterface_issue24720() throws IOExc .doesNotHaveParameter("pageable"); } + @Test + public void nullSchemaDefaultIsNotRenderedAsSpringRequestParamDefault() throws IOException { + Map additionalProperties = new HashMap<>(); + additionalProperties.put(INTERFACE_ONLY, true); + additionalProperties.put(SKIP_DEFAULT_INTERFACE, true); + additionalProperties.put(USE_SPRING_BOOT4, true); + additionalProperties.put("useJackson3", true); + additionalProperties.put(USE_JSPECIFY, true); + additionalProperties.put(USE_DEDUCTION_FOR_ONE_OF_INTERFACES, true); + additionalProperties.put(AbstractJavaCodegen.CONTAINER_DEFAULT_TO_NULL, true); + additionalProperties.put(GENERATE_JSON_INCLUDE_ANNOTATIONS, true); + additionalProperties.put(PERFORM_BEANVALIDATION, true); + additionalProperties.put(AbstractJavaCodegen.OPENAPI_NULLABLE, false); + + Map files = generateFromContract( + "src/test/resources/3_1/spring/optional-query-null-default.yaml", SPRING_HTTP_INTERFACE, additionalProperties); + + JavaFileAssert api = JavaFileAssert.assertThat(files.get("PlacesApi.java")); + api.assertMethod("getPlaces") + .assertParameter("ids").hasType("List") + .assertParameterAnnotations() + .containsWithNameAndDoesNotContainAttributes("RequestParam", List.of("defaultValue")); + api.assertMethod("getPlaces") + .assertParameter("search") + .assertParameterAnnotations() + .containsWithNameAndDoesNotContainAttributes("RequestParam", List.of("defaultValue")); + api.assertMethod("getPlaces") + .assertParameter("limit") + .assertParameterAnnotations() + .containsWithNameAndAttributes("RequestParam", ImmutableMap.of("defaultValue", "\"10\"")); + api.assertMethod("getPlaces") + .assertParameter("requiredIds") + .assertParameterAnnotations() + .containsWithNameAndAttributes("RequestParam", ImmutableMap.of("required", "true")); + api.assertMethod("getPlaces") + .assertParameter("defaultIds") + .assertParameterAnnotations() + .containsWithNameAndAttributes("RequestParam", ImmutableMap.of("defaultValue", "\"a,b\"")); + api.assertMethod("getPlaces") + .assertParameter("literalNull") + .assertParameterAnnotations() + .containsWithNameAndAttributes("RequestParam", ImmutableMap.of("defaultValue", "\"null\"")); + api.assertMethod("getPlaces") + .assertParameter("referencedLiteralNull") + .assertParameterAnnotations() + .containsWithNameAndAttributes("RequestParam", ImmutableMap.of("defaultValue", "\"null\"")); + api.assertMethod("getPlaces") + .assertParameter("referencedNullDefault") + .assertParameterAnnotations() + .containsWithNameAndDoesNotContainAttributes("RequestParam", List.of("defaultValue")); + } + @Test public void explicitXSpringPaginatedFalseKeepsQueryParamsForSpringCloud_issue24720() throws IOException { // Regression #24720: x-spring-paginated: false on a spring-cloud operation must NOT be diff --git a/modules/openapi-generator/src/test/resources/3_1/spring/optional-query-null-default.yaml b/modules/openapi-generator/src/test/resources/3_1/spring/optional-query-null-default.yaml new file mode 100644 index 000000000000..7fd268572cf2 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_1/spring/optional-query-null-default.yaml @@ -0,0 +1,68 @@ +openapi: 3.1.0 +info: + title: Optional query null default + version: 1.0.0 +paths: + /places: + get: + operationId: getPlaces + parameters: + - name: ids + in: query + required: false + schema: + type: array + items: + type: string + default: null + - name: search + in: query + required: false + schema: + type: string + - name: limit + in: query + required: false + schema: + type: integer + default: 10 + - name: requiredIds + in: query + required: true + schema: + type: array + items: + type: string + - name: defaultIds + in: query + required: false + schema: + type: array + items: + type: string + default: [a, b] + - name: literalNull + in: query + required: false + schema: + type: string + default: "null" + - name: referencedLiteralNull + in: query + required: false + schema: + $ref: '#/components/schemas/stringWithNullDefault' + default: "null" + - name: referencedNullDefault + in: query + required: false + schema: + $ref: '#/components/schemas/stringWithNullDefault' + responses: + "200": + description: OK +components: + schemas: + stringWithNullDefault: + type: string + default: null