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 13f5f47ad537..6dcbd33676f3 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 @@ -1558,7 +1558,17 @@ private String toObjectDefaultValue(CodegenProperty cp, Object defaultValue, Map } String defaultPropertyExpression = null; - if(ModelUtils.isLongSchema(propertySchema)) { + if(ModelUtils.isEnumSchema(ModelUtils.getReferencedSchema(this.openAPI, propertySchema))) { + // Enum-typed property: render the enum constant (e.g. `OutputFormat.OrderEnum.SIMILARITY`) + // rather than a raw quoted string, which would not compile (see #24298). + CodegenProperty enumProperty = fromProperty(key, propertySchema); + String enumType = enumProperty.isEnum + // an inline enum is generated as a nested class of the containing object type + ? cp.datatypeWithEnum + "." + enumProperty.datatypeWithEnum + // a `$ref` to a named enum is a top-level type + : enumProperty.datatypeWithEnum; + defaultPropertyExpression = enumType + "." + toEnumVarName(value.asText(), enumProperty.dataType); + } else if(ModelUtils.isLongSchema(propertySchema)) { defaultPropertyExpression = value.asText()+"l"; } else if(ModelUtils.isIntegerSchema(propertySchema)) { defaultPropertyExpression = value.asText(); 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 b0f6c2b4f0f3..a77716ce9bc5 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 @@ -650,6 +650,28 @@ public void toDefaultValueForComposedObjectWithDefaultTest() { Assert.assertEquals(rendered, "new " + cp.datatypeWithEnum + "().one(\"one\").two(\"two\")"); } + @Test + public void toDefaultValueForObjectWithEnumPropertyDefaultTest() { + // An object default that contains an enum property must render the enum constant + // (e.g. `OutputFormat.OrderEnum.SIMILARITY`) rather than a raw quoted string, which + // would not compile (see #24298). + ObjectSchema outputFormat = new ObjectSchema(); + outputFormat.addProperty("order", new StringSchema()._enum(java.util.Arrays.asList("IMPORTANCE", "SIMILARITY"))); + outputFormat.addProperty("limit", new IntegerSchema()); + Map defaultValue = new LinkedHashMap<>(); + defaultValue.put("order", "SIMILARITY"); + defaultValue.put("limit", 10); + outputFormat.setDefault(defaultValue); + + codegen.setOpenAPI(new OpenAPI().components(new Components().addSchemas("OutputFormat", outputFormat))); + + CodegenProperty cp = codegen.fromProperty("format", new Schema<>().$ref("#/components/schemas/OutputFormat")); + String rendered = codegen.toDefaultValue(cp, outputFormat); + + Assert.assertEquals(rendered, "new " + cp.datatypeWithEnum + "().order(" + + cp.datatypeWithEnum + ".OrderEnum.SIMILARITY).limit(10)"); + } + @Test public void dateDefaultValueIsIsoDate() { final OpenAPI openAPI = FLATTENED_SPEC.get("3_0/spring/date-time-parameter-types-for-testing"); 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 4de80e62b901..c3f5290b4067 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 @@ -1850,6 +1850,25 @@ public void testJavaClientDefaultValues_issueNoNumber() { .asString().endsWith("= new ArrayList<>();"); } + @Test + public void testObjectDefaultWithEnumProperty_issue24298() { + final Path output = newTempFolder(); + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName(JAVA_GENERATOR) + .setInputSpec("src/test/resources/bugs/issue_24298.yaml") + .setOutputDir(output.toString().replace("\\", "/")); + + Map files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate().stream() + .collect(Collectors.toMap(File::getName, Function.identity())); + + // The `format` field's default is an OutputFormat whose `order` property is an inline enum. It must + // be rendered as the enum constant, not a raw quoted string, otherwise the code does not compile (#24298). + JavaFileAssert.assertThat(files.get("Formatter.java")) + .assertProperty("format") + .asString() + .contains("new OutputFormat().order(OutputFormat.OrderEnum.SIMILARITY).limit(10)"); + } + @Test public void testWebClientJsonCreatorWithNullable_issue12790() { final Path output = newTempFolder(); diff --git a/modules/openapi-generator/src/test/resources/bugs/issue_24298.yaml b/modules/openapi-generator/src/test/resources/bugs/issue_24298.yaml new file mode 100644 index 000000000000..1f5c351b8c58 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/bugs/issue_24298.yaml @@ -0,0 +1,25 @@ +openapi: "3.1.0" +info: + title: Enum Default Issue Demo + version: 1.0.0 +paths: {} +components: + schemas: + OutputFormat: + type: object + properties: + order: + type: string + enum: + - IMPORTANCE + - SIMILARITY + limit: + type: integer + default: + order: SIMILARITY + limit: 10 + Formatter: + type: object + properties: + format: + $ref: '#/components/schemas/OutputFormat'