From 215eab89b578e654bf9a215f3cd6f492b49efb39 Mon Sep 17 00:00:00 2001 From: Jachym Metlicka Date: Sat, 25 Apr 2026 01:16:01 +0200 Subject: [PATCH] feat(kotlin): add bestEffortBacktick naming option for Kotlin enums --- bin/configs/kotlin-enum-default-value.yaml | 1 + docs/generators/kotlin-misk.md | 2 +- docs/generators/kotlin-server.md | 2 +- docs/generators/kotlin-spring.md | 2 +- docs/generators/kotlin-vertx.md | 2 +- docs/generators/kotlin-wiremock.md | 2 +- docs/generators/kotlin.md | 2 +- docs/generators/ktorm-schema.md | 2 +- .../languages/AbstractKotlinCodegen.java | 52 ++++++++- .../kotlin/AbstractKotlinCodegenTest.java | 77 +++++++++++++ .../kotlin/issue10591-enum-defaultValue.yaml | 27 +++++ .../.openapi-generator/FILES | 2 + .../kotlin-enum-default-value/README.md | 1 + .../docs/ComplexEnum.md | 36 ++++++ .../client/infrastructure/SerializerHelper.kt | 2 + .../openapitools/client/models/ComplexEnum.kt | 107 ++++++++++++++++++ .../client/models/PropertyOfDay.kt | 26 ++--- .../client/models/ComplexEnumTest.kt | 37 ++++++ 18 files changed, 357 insertions(+), 25 deletions(-) create mode 100644 samples/client/petstore/kotlin-enum-default-value/docs/ComplexEnum.md create mode 100644 samples/client/petstore/kotlin-enum-default-value/src/main/kotlin/org/openapitools/client/models/ComplexEnum.kt create mode 100644 samples/client/petstore/kotlin-enum-default-value/src/test/kotlin/org/openapitools/client/models/ComplexEnumTest.kt diff --git a/bin/configs/kotlin-enum-default-value.yaml b/bin/configs/kotlin-enum-default-value.yaml index b27ccfd73afb..502bdcf07eb5 100644 --- a/bin/configs/kotlin-enum-default-value.yaml +++ b/bin/configs/kotlin-enum-default-value.yaml @@ -7,5 +7,6 @@ additionalProperties: serializableModel: "true" dateLibrary: java8 enumUnknownDefaultCase: true + enumPropertyNaming: bestEffortBacktick enumNameMappings: CHRISTMAS_DAY: XMAS_DAY diff --git a/docs/generators/kotlin-misk.md b/docs/generators/kotlin-misk.md index b0aa29064a10..3832b9120655 100644 --- a/docs/generators/kotlin-misk.md +++ b/docs/generators/kotlin-misk.md @@ -29,7 +29,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |apiSuffix|suffix for api classes| |Api| |artifactId|Generated artifact id (name of jar).| |null| |artifactVersion|Generated artifact's package version.| |1.0.0| -|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |original| +|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', 'original', and 'bestEffortBacktick' (like 'original' but tries to wrap values in backticks before falling back to sanitizing, e.g. `name,asc` stays `name,asc` rather than becoming nameCommaAsc; useful for sort/order enums)| |original| |generateStubImplClasses|Generate Stub Impl Classes| |false| |groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools| |implicitHeaders|Skip header parameters in the generated API methods.| |false| diff --git a/docs/generators/kotlin-server.md b/docs/generators/kotlin-server.md index 31f042e5128f..da36df26ba13 100644 --- a/docs/generators/kotlin-server.md +++ b/docs/generators/kotlin-server.md @@ -22,7 +22,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |apiSuffix|suffix for api classes| |Api| |artifactId|Generated artifact id (name of jar).| |kotlin-server| |artifactVersion|Generated artifact's package version.| |1.0.0| -|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |original| +|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', 'original', and 'bestEffortBacktick' (like 'original' but tries to wrap values in backticks before falling back to sanitizing, e.g. `name,asc` stays `name,asc` rather than becoming nameCommaAsc; useful for sort/order enums)| |original| |featureAutoHead|Automatically provide responses to HEAD requests for existing routes that have the GET verb defined.| |true| |featureCORS|Ktor by default provides an interceptor for implementing proper support for Cross-Origin Resource Sharing (CORS). See enable-cors.org.| |false| |featureCompression|Adds ability to compress outgoing content using gzip, deflate or custom encoder and thus reduce size of the response.| |true| diff --git a/docs/generators/kotlin-spring.md b/docs/generators/kotlin-spring.md index 529456315dda..bf4393ae41f2 100644 --- a/docs/generators/kotlin-spring.md +++ b/docs/generators/kotlin-spring.md @@ -32,7 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |declarativeInterfaceReactiveMode|What type of reactive style to use in Spring Http declarative interface|
**coroutines**
Use kotlin-idiomatic 'suspend' functions
**reactor**
Use reactor return wrappers 'Mono' and 'Flux'
|coroutines| |delegatePattern|Whether to generate the server files using the delegate pattern| |false| |documentationProvider|Select the OpenAPI documentation provider.|
**none**
Do not publish an OpenAPI specification.
**source**
Publish the original input OpenAPI specification.
**springdoc**
Generate an OpenAPI 3 specification using SpringDoc.
|springdoc| -|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |original| +|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', 'original', and 'bestEffortBacktick' (like 'original' but tries to wrap values in backticks before falling back to sanitizing, e.g. `name,asc` stays `name,asc` rather than becoming nameCommaAsc; useful for sort/order enums)| |original| |exceptionHandler|generate default global exception handlers (not compatible with reactive. enabling reactive will disable exceptionHandler )| |true| |generatePageableConstraintValidation|Generate a @ValidPageable annotation and PageableConstraintValidator class, and apply @ValidPageable to the injected Pageable parameter of operations whose 'page' or 'size' parameter specifies a maximum constraint. The annotation enforces those constraints on the Pageable object that replaces the individual page/size query parameters. Requires useBeanValidation=true and library=spring-boot.| |false| |generateSortValidation|Generate a @ValidSort annotation and SortValidator class, and apply @ValidSort to the injected Pageable parameter of operations whose 'sort' parameter has enum values. The annotation validates that sort values in the Pageable object match the allowed enum values from the spec. Requires useBeanValidation=true and library=spring-boot.| |false| diff --git a/docs/generators/kotlin-vertx.md b/docs/generators/kotlin-vertx.md index 279e7330f4e4..6cdc16bed8c1 100644 --- a/docs/generators/kotlin-vertx.md +++ b/docs/generators/kotlin-vertx.md @@ -22,7 +22,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |apiSuffix|suffix for api classes| |Api| |artifactId|Generated artifact id (name of jar).| |null| |artifactVersion|Generated artifact's package version.| |1.0.0| -|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |original| +|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', 'original', and 'bestEffortBacktick' (like 'original' but tries to wrap values in backticks before falling back to sanitizing, e.g. `name,asc` stays `name,asc` rather than becoming nameCommaAsc; useful for sort/order enums)| |original| |groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools| |implicitHeaders|Skip header parameters in the generated API methods.| |false| |modelMutable|Create mutable models| |false| diff --git a/docs/generators/kotlin-wiremock.md b/docs/generators/kotlin-wiremock.md index 8bd595b2e4e5..b02b15fb3596 100644 --- a/docs/generators/kotlin-wiremock.md +++ b/docs/generators/kotlin-wiremock.md @@ -22,7 +22,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |apiSuffix|suffix for api classes| |Api| |artifactId|Generated artifact id (name of jar).| |null| |artifactVersion|Generated artifact's package version.| |1.0.0| -|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |original| +|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', 'original', and 'bestEffortBacktick' (like 'original' but tries to wrap values in backticks before falling back to sanitizing, e.g. `name,asc` stays `name,asc` rather than becoming nameCommaAsc; useful for sort/order enums)| |original| |groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools| |implicitHeaders|Skip header parameters in the generated API methods.| |false| |modelMutable|Create mutable models| |false| diff --git a/docs/generators/kotlin.md b/docs/generators/kotlin.md index 7e79ba98bfc8..981ed1e016bb 100644 --- a/docs/generators/kotlin.md +++ b/docs/generators/kotlin.md @@ -25,7 +25,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |collectionType|Option. Collection type to use|
**array**
kotlin.Array
**list**
kotlin.collections.List
|list| |companionObject|Whether to generate companion objects in data classes, enabling companion extensions.| |false| |dateLibrary|Option. Date library to use|
**threetenbp-localdatetime**
Threetenbp - Backport of JSR310 (jvm only, for legacy app only)
**kotlinx-datetime**
kotlinx-datetime (preferred for multiplatform)
**string**
String
**java8-localdatetime**
Java 8 native JSR310 (jvm only, for legacy app only)
**java8**
Java 8 native JSR310 (jvm only, preferred for jdk 1.8+)
**threetenbp**
Threetenbp - Backport of JSR310 (jvm only, preferred for jdk < 1.8)
|java8| -|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |original| +|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', 'original', and 'bestEffortBacktick' (like 'original' but tries to wrap values in backticks before falling back to sanitizing, e.g. `name,asc` stays `name,asc` rather than becoming nameCommaAsc; useful for sort/order enums)| |original| |explicitApi|Generates code with explicit access modifiers to comply with Kotlin Explicit API Mode.| |false| |failOnUnknownProperties|Fail Jackson de-serialization on unknown properties| |false| |generateOneOfAnyOfWrappers|Generate oneOf, anyOf schemas as wrappers. Only `jvm-retrofit2`(library) with `gson` or `kotlinx_serialization`(serializationLibrary) support this option.| |false| diff --git a/docs/generators/ktorm-schema.md b/docs/generators/ktorm-schema.md index 179d7c7647c0..4b905a59a220 100644 --- a/docs/generators/ktorm-schema.md +++ b/docs/generators/ktorm-schema.md @@ -23,7 +23,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |artifactId|Generated artifact id (name of jar).| |ktorm| |artifactVersion|Generated artifact's package version.| |1.0.0| |defaultDatabaseName|Default database name for all queries| |sqlite.db| -|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |original| +|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', 'original', and 'bestEffortBacktick' (like 'original' but tries to wrap values in backticks before falling back to sanitizing, e.g. `name,asc` stays `name,asc` rather than becoming nameCommaAsc; useful for sort/order enums)| |original| |groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools| |identifierNamingConvention|Naming convention of Ktorm identifiers(table names and column names). This is not related to database name which is defined by defaultDatabaseName option|
**original**
Do not transform original names
**snake_case**
Use snake_case names
|original| |implicitHeaders|Skip header parameters in the generated API methods.| |false| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java index cd130c766530..e49181d74df7 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java @@ -91,7 +91,34 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co @Setter protected boolean nonPublicApi = false; - @Getter protected CodegenConstants.ENUM_PROPERTY_NAMING_TYPE enumPropertyNaming = CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.original; + /** + * Naming convention options for Kotlin enum properties. Extends the shared + * {@link org.openapitools.codegen.CodegenConstants.ENUM_PROPERTY_NAMING_TYPE} with + * Kotlin-specific options so that Kotlin generators are not forced to add language-specific + * values to the shared enum (which cannot be extended in Java). + */ + public enum KotlinEnumNamingType { + camelCase, PascalCase, snake_case, original, UPPERCASE, + /** + * Like {@code original}, but uses Kotlin's backtick-escaped identifier syntax to preserve + * more values without falling back to sanitization. Where {@code original} would silently + * replace characters (e.g. {@code in-progress} → {@code inMinusProgress}), this option + * wraps the value in backticks instead (e.g. {@code `in-progress`}). + *

+ * Particularly useful for sort/order enums whose values contain commas or other punctuation, + * e.g. {@code name,asc}, {@code name,desc}, {@code id,asc}, {@code id,desc} — these are + * preserved as `name,asc` etc. rather than being mangled into {@code nameCommaAsc}. + *

+ * + */ + bestEffortBacktick + } + + @Getter protected KotlinEnumNamingType enumPropertyNaming = KotlinEnumNamingType.original; // model classes cannot use the same property names defined in HashMap // ref: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-hash-map/ @@ -287,7 +314,11 @@ public AbstractKotlinCodegen() { addOption(CodegenConstants.ARTIFACT_ID, "Generated artifact id (name of jar).", artifactId); addOption(CodegenConstants.ARTIFACT_VERSION, "Generated artifact's package version.", artifactVersion); - CliOption enumPropertyNamingOpt = new CliOption(CodegenConstants.ENUM_PROPERTY_NAMING, CodegenConstants.ENUM_PROPERTY_NAMING_DESC); + CliOption enumPropertyNamingOpt = new CliOption(CodegenConstants.ENUM_PROPERTY_NAMING, + "Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case'," + + " 'UPPERCASE', 'original', and 'bestEffortBacktick' (like 'original'" + + " but tries to wrap values in backticks before falling back to sanitizing, e.g. `name,asc` stays" + + " `name,asc` rather than becoming nameCommaAsc; useful for sort/order enums)"); cliOptions.add(enumPropertyNamingOpt.defaultValue(enumPropertyNaming.name())); cliOptions.add(new CliOption(CodegenConstants.PARCELIZE_MODELS, CodegenConstants.PARCELIZE_MODELS_DESC)); @@ -341,14 +372,14 @@ public String escapeUnsafeCharacters(String input) { /** * Sets the naming convention for Kotlin enum properties * - * @param enumPropertyNamingType The string representation of the naming convention, as defined by {@link org.openapitools.codegen.CodegenConstants.ENUM_PROPERTY_NAMING_TYPE} + * @param enumPropertyNamingType The string representation of the naming convention, as defined by {@link KotlinEnumNamingType} */ public void setEnumPropertyNaming(final String enumPropertyNamingType) { try { - this.enumPropertyNaming = CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.valueOf(enumPropertyNamingType); + this.enumPropertyNaming = KotlinEnumNamingType.valueOf(enumPropertyNamingType); } catch (IllegalArgumentException ex) { StringBuilder sb = new StringBuilder(enumPropertyNamingType + " is an invalid enum property naming option. Please choose from:"); - for (CodegenConstants.ENUM_PROPERTY_NAMING_TYPE t : CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.values()) { + for (KotlinEnumNamingType t : KotlinEnumNamingType.values()) { sb.append("\n ").append(t.name()); } throw new RuntimeException(sb.toString()); @@ -682,6 +713,17 @@ public String toEnumVarName(String value, String datatype) { case UPPERCASE: modified = underscore(modified).toUpperCase(Locale.ROOT); break; + case bestEffortBacktick: + // Use the original value as a plain identifier if already valid and not reserved. + if (!reservedWords.contains(value) && value.matches("[a-zA-Z_$][a-zA-Z0-9_$]*")) { + return value; + } + // Wrap in backticks when the value contains no character that is illegal inside them. + if (!value.contains("`") && !value.contains("\n") && !value.contains("\r") && !value.contains("\0")) { + return "`" + value + "`"; + } + // Fall back: use the already-sanitized modified (pre-switch value). + break; } if (reservedWords.contains(modified)) { diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/AbstractKotlinCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/AbstractKotlinCodegenTest.java index fe04c75e18d7..a5e8b44c9483 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/AbstractKotlinCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/AbstractKotlinCodegenTest.java @@ -18,6 +18,7 @@ import java.io.File; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; @@ -25,6 +26,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.withSettings; import static org.openapitools.codegen.CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.*; +import static org.openapitools.codegen.languages.AbstractKotlinCodegen.KotlinEnumNamingType.bestEffortBacktick; import static org.openapitools.codegen.TestUtils.createCodegenModelWrapper; import static org.testng.Assert.*; @@ -80,6 +82,81 @@ public void originalEnumConverter() { assertEquals(codegen.toEnumVarName("data/*", null), "dataSlashStar"); } + @Test + public void bestEffortBacktickEnumConverter() { + codegen.setEnumPropertyNaming(bestEffortBacktick.name()); + + // Already a valid plain Kotlin identifier — no backticks needed + assertEquals(codegen.toEnumVarName("validName", null), "validName"); + assertEquals(codegen.toEnumVarName("snake_case", null), "snake_case"); + + // Contains characters invalid in a plain identifier — wrap in backticks + assertEquals(codegen.toEnumVarName("long Name", null), "`long Name`"); + assertEquals(codegen.toEnumVarName("long-Name", null), "`long-Name`"); + assertEquals(codegen.toEnumVarName("not1long Name", null), "`not1long Name`"); + assertEquals(codegen.toEnumVarName("data/*", null), "`data/*`"); + + // Starts with a digit — not a valid plain identifier, wrap in backticks + assertEquals(codegen.toEnumVarName("1long Name", null), "`1long Name`"); + + // Kotlin reserved word — wrap in backticks to make it valid + assertEquals(codegen.toEnumVarName("fun", null), "`fun`"); + assertEquals(codegen.toEnumVarName("class", null), "`class`"); + + // Emoji — Unicode Symbol category, not a letter, so invalid as plain identifier; valid inside backticks + assertEquals(codegen.toEnumVarName("🎉", null), "`🎉`"); + + // Dollar sign is valid in plain Kotlin identifiers — no backticks needed + assertEquals(codegen.toEnumVarName("$price", null), "$price"); + + // Contains a literal backtick — cannot use backtick escaping, fall back to sanitization + assertEquals(codegen.toEnumVarName("foo`bar", null), "fooBacktickBar"); + } + + @Test(description = "bestEffortBacktick preserves original values as backtick identifiers in ComplexEnum") + public void testComplexEnumFromSpecWithBestEffortBacktick() { + codegen.setEnumPropertyNaming(bestEffortBacktick.name()); + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/kotlin/issue10591-enum-defaultValue.yaml"); + codegen.setOpenAPI(openAPI); + + Schema complexEnumSchema = openAPI.getComponents().getSchemas().get("ComplexEnum"); + CodegenModel cm = codegen.fromModel("ComplexEnum", complexEnumSchema); + codegen.postProcessModels(createCodegenModelWrapper(cm)); + + @SuppressWarnings("unchecked") + List> enumVars = (List>) cm.allowableValues.get("enumVars"); + List names = enumVars.stream() + .map(e -> (String) e.get("name")) + .collect(Collectors.toList()); + + // Already valid plain Kotlin identifiers — used as-is + assertTrue(names.contains("active")); + assertTrue(names.contains("inactive")); + assertTrue(names.contains("$yolo")); + + // Contain a hyphen — wrapped in backticks + assertTrue(names.contains("`in-progress`")); + assertTrue(names.contains("`not-started`")); + + // Sort/order enum values containing a comma — wrapped in backticks + assertTrue(names.contains("`name,asc`")); + assertTrue(names.contains("`name,desc`")); + assertTrue(names.contains("`id,asc`")); + assertTrue(names.contains("`id,desc`")); + + // Contains a space — wrapped in backticks + assertTrue(names.contains("`not started`")); + + // Kotlin reserved word — wrapped in backticks + assertTrue(names.contains("`class`")); + + // Contains a literal backtick — cannot use backtick escaping, falls back to sanitization + assertTrue(names.contains("fooBacktickBar")); + + // Contains emoji — wrapped in backticks + assertTrue(names.contains("`🎉`")); + } + @Test public void pascalCaseEnumConverter() { codegen.setEnumPropertyNaming(PascalCase.name()); diff --git a/modules/openapi-generator/src/test/resources/3_0/kotlin/issue10591-enum-defaultValue.yaml b/modules/openapi-generator/src/test/resources/3_0/kotlin/issue10591-enum-defaultValue.yaml index 531c1d0de024..1436ec9df1eb 100644 --- a/modules/openapi-generator/src/test/resources/3_0/kotlin/issue10591-enum-defaultValue.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/kotlin/issue10591-enum-defaultValue.yaml @@ -102,3 +102,30 @@ components: - CHRISTMAS_DAY - BOXING_DAY description: The DayType describe during which the assignment applies + # Demonstrates bestEffortBacktick: sort/order enum values that contain commas and hyphens + # are preserved as backtick-escaped identifiers (e.g. `name,asc`) instead of being mangled. + ComplexEnum: + type: string + enum: + # Already valid plain Kotlin identifiers — used as-is + - active + - inactive + # Contain a hyphen — wrapped in backticks: `in-progress`, `not-started` + - in-progress + - not-started + # Contain a comma — typical sort/order values; wrapped in backticks + - "name,asc" + - "name,desc" + - "id,asc" + - "id,desc" + # Contains a space — wrapped in backticks + - "not started" + # Kotlin reserved word — wrapped in backticks: `class` + - class + # Contains a backtick — cannot use backtick escaping, falls back to sanitization: fooBacktickBar + - "foo`bar" + # starts with $ symbol - no need for backticks + - $yolo + # emoji + - 🎉 + diff --git a/samples/client/petstore/kotlin-enum-default-value/.openapi-generator/FILES b/samples/client/petstore/kotlin-enum-default-value/.openapi-generator/FILES index 5ae41b2e84f1..87c993aae634 100644 --- a/samples/client/petstore/kotlin-enum-default-value/.openapi-generator/FILES +++ b/samples/client/petstore/kotlin-enum-default-value/.openapi-generator/FILES @@ -1,5 +1,6 @@ README.md build.gradle +docs/ComplexEnum.md docs/DefaultApi.md docs/ModelWithEnumPropertyHavingDefault.md docs/PropertyOfDay.md @@ -27,5 +28,6 @@ src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt src/main/kotlin/org/openapitools/client/infrastructure/SerializerHelper.kt src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt +src/main/kotlin/org/openapitools/client/models/ComplexEnum.kt src/main/kotlin/org/openapitools/client/models/ModelWithEnumPropertyHavingDefault.kt src/main/kotlin/org/openapitools/client/models/PropertyOfDay.kt diff --git a/samples/client/petstore/kotlin-enum-default-value/README.md b/samples/client/petstore/kotlin-enum-default-value/README.md index 47ab4e8997d6..e286a0fbf066 100644 --- a/samples/client/petstore/kotlin-enum-default-value/README.md +++ b/samples/client/petstore/kotlin-enum-default-value/README.md @@ -51,6 +51,7 @@ All URIs are relative to *http://localhost* ## Documentation for Models + - [org.openapitools.client.models.ComplexEnum](docs/ComplexEnum.md) - [org.openapitools.client.models.ModelWithEnumPropertyHavingDefault](docs/ModelWithEnumPropertyHavingDefault.md) - [org.openapitools.client.models.PropertyOfDay](docs/PropertyOfDay.md) diff --git a/samples/client/petstore/kotlin-enum-default-value/docs/ComplexEnum.md b/samples/client/petstore/kotlin-enum-default-value/docs/ComplexEnum.md new file mode 100644 index 000000000000..491a1a3f7b1c --- /dev/null +++ b/samples/client/petstore/kotlin-enum-default-value/docs/ComplexEnum.md @@ -0,0 +1,36 @@ + +# ComplexEnum + +## Enum + + + * `active` (value: `"active"`) + + * `inactive` (value: `"inactive"`) + + * ``in-progress`` (value: `"in-progress"`) + + * ``not-started`` (value: `"not-started"`) + + * ``name,asc`` (value: `"name,asc"`) + + * ``name,desc`` (value: `"name,desc"`) + + * ``id,asc`` (value: `"id,asc"`) + + * ``id,desc`` (value: `"id,desc"`) + + * ``not started`` (value: `"not started"`) + + * ``class`` (value: `"class"`) + + * `fooBacktickBar` (value: `"foo`bar"`) + + * `$yolo` (value: `"$yolo"`) + + * ``🎉`` (value: `"🎉"`) + + * `unknown_default_open_api` (value: `"unknown_default_open_api"`) + + + diff --git a/samples/client/petstore/kotlin-enum-default-value/src/main/kotlin/org/openapitools/client/infrastructure/SerializerHelper.kt b/samples/client/petstore/kotlin-enum-default-value/src/main/kotlin/org/openapitools/client/infrastructure/SerializerHelper.kt index aae522c65f63..420b3c3c22b8 100644 --- a/samples/client/petstore/kotlin-enum-default-value/src/main/kotlin/org/openapitools/client/infrastructure/SerializerHelper.kt +++ b/samples/client/petstore/kotlin-enum-default-value/src/main/kotlin/org/openapitools/client/infrastructure/SerializerHelper.kt @@ -6,6 +6,8 @@ import com.squareup.moshi.adapters.EnumJsonAdapter object SerializerHelper { fun addEnumUnknownDefaultCase(moshiBuilder: Moshi.Builder): Moshi.Builder { return moshiBuilder + .add(org.openapitools.client.models.ComplexEnum::class.java, EnumJsonAdapter.create(org.openapitools.client.models.ComplexEnum::class.java) + .withUnknownFallback(org.openapitools.client.models.ComplexEnum.unknown_default_open_api)) .add(org.openapitools.client.models.ModelWithEnumPropertyHavingDefault.PropertyName::class.java, EnumJsonAdapter.create(org.openapitools.client.models.ModelWithEnumPropertyHavingDefault.PropertyName::class.java) .withUnknownFallback(org.openapitools.client.models.ModelWithEnumPropertyHavingDefault.PropertyName.unknown_default_open_api)) .add(org.openapitools.client.models.PropertyOfDay.DaysOfWeek::class.java, EnumJsonAdapter.create(org.openapitools.client.models.PropertyOfDay.DaysOfWeek::class.java) diff --git a/samples/client/petstore/kotlin-enum-default-value/src/main/kotlin/org/openapitools/client/models/ComplexEnum.kt b/samples/client/petstore/kotlin-enum-default-value/src/main/kotlin/org/openapitools/client/models/ComplexEnum.kt new file mode 100644 index 000000000000..f7d0e0d2fced --- /dev/null +++ b/samples/client/petstore/kotlin-enum-default-value/src/main/kotlin/org/openapitools/client/models/ComplexEnum.kt @@ -0,0 +1,107 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package org.openapitools.client.models + + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * + * + * Values: active,inactive,`in-progress`,`not-started`,`name,asc`,`name,desc`,`id,asc`,`id,desc`,`not started`,`class`,fooBacktickBar,$yolo,`🎉`,unknown_default_open_api + */ + +@JsonClass(generateAdapter = false) +enum class ComplexEnum(val value: kotlin.String) { + + @Json(name = "active") + active("active"), + + @Json(name = "inactive") + inactive("inactive"), + + @Json(name = "in-progress") + `in-progress`("in-progress"), + + @Json(name = "not-started") + `not-started`("not-started"), + + @Json(name = "name,asc") + `name,asc`("name,asc"), + + @Json(name = "name,desc") + `name,desc`("name,desc"), + + @Json(name = "id,asc") + `id,asc`("id,asc"), + + @Json(name = "id,desc") + `id,desc`("id,desc"), + + @Json(name = "not started") + `not started`("not started"), + + @Json(name = "class") + `class`("class"), + + @Json(name = "foo`bar") + fooBacktickBar("foo`bar"), + + @Json(name = "$yolo") + $yolo("$yolo"), + + @Json(name = "🎉") + `🎉`("🎉"), + + @Json(name = "unknown_default_open_api") + unknown_default_open_api("unknown_default_open_api"); + + /** + * Override [toString()] to avoid using the enum variable name as the value, and instead use + * the actual value defined in the API spec file. + * + * This solves a problem when the variable name and its value are different, and ensures that + * the client sends the correct enum values to the server always. + */ + override fun toString(): kotlin.String = value + + companion object { + /** + * Converts the provided [data] to a [String] on success, null otherwise. + */ + fun encode(data: kotlin.Any?): kotlin.String? = if (data is ComplexEnum) "$data" else null + + /** + * Returns a valid [ComplexEnum] for [data], null otherwise. + */ + fun decode(data: kotlin.Any?): ComplexEnum? = data?.let { + val normalizedData = "$it".lowercase() + entries.firstOrNull { value -> + it == value || normalizedData == "$value".lowercase() + } + } + } +} + diff --git a/samples/client/petstore/kotlin-enum-default-value/src/main/kotlin/org/openapitools/client/models/PropertyOfDay.kt b/samples/client/petstore/kotlin-enum-default-value/src/main/kotlin/org/openapitools/client/models/PropertyOfDay.kt index 72b61ebf5133..2b3af56d4572 100644 --- a/samples/client/petstore/kotlin-enum-default-value/src/main/kotlin/org/openapitools/client/models/PropertyOfDay.kt +++ b/samples/client/petstore/kotlin-enum-default-value/src/main/kotlin/org/openapitools/client/models/PropertyOfDay.kt @@ -93,22 +93,22 @@ data class PropertyOfDay ( /** * Month of year * - * Values: _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,unknown_default_open_api + * Values: `1`,`2`,`3`,`4`,`5`,`6`,`7`,`8`,`9`,`10`,`11`,`12`,unknown_default_open_api */ @JsonClass(generateAdapter = false) enum class MonthOfYear(val value: kotlin.Int) { - @Json(name = "1") _1(1), - @Json(name = "2") _2(2), - @Json(name = "3") _3(3), - @Json(name = "4") _4(4), - @Json(name = "5") _5(5), - @Json(name = "6") _6(6), - @Json(name = "7") _7(7), - @Json(name = "8") _8(8), - @Json(name = "9") _9(9), - @Json(name = "10") _10(10), - @Json(name = "11") _11(11), - @Json(name = "12") _12(12), + @Json(name = "1") `1`(1), + @Json(name = "2") `2`(2), + @Json(name = "3") `3`(3), + @Json(name = "4") `4`(4), + @Json(name = "5") `5`(5), + @Json(name = "6") `6`(6), + @Json(name = "7") `7`(7), + @Json(name = "8") `8`(8), + @Json(name = "9") `9`(9), + @Json(name = "10") `10`(10), + @Json(name = "11") `11`(11), + @Json(name = "12") `12`(12), @Json(name = "11184809") unknown_default_open_api(11184809); } /** diff --git a/samples/client/petstore/kotlin-enum-default-value/src/test/kotlin/org/openapitools/client/models/ComplexEnumTest.kt b/samples/client/petstore/kotlin-enum-default-value/src/test/kotlin/org/openapitools/client/models/ComplexEnumTest.kt new file mode 100644 index 000000000000..ad21562efa37 --- /dev/null +++ b/samples/client/petstore/kotlin-enum-default-value/src/test/kotlin/org/openapitools/client/models/ComplexEnumTest.kt @@ -0,0 +1,37 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package org.openapitools.client.models + +import io.kotlintest.shouldBe +import io.kotlintest.specs.ShouldSpec + +import org.openapitools.client.models.ComplexEnum + +class ComplexEnumTest : ShouldSpec() { + init { + // uncomment below to create an instance of ComplexEnum + //val modelInstance = ComplexEnum() + + } +}