Skip to content

[kotlin][kotlin-spring] Keep the Map type for properties whose additionalProperties is an inline enum - #25474

Open
fixfon wants to merge 1 commit into
OpenAPITools:masterfrom
fixfon:fix/25453-kotlin-map-inline-enum-type
Open

fixfon wants to merge 1 commit into
OpenAPITools:masterfrom
fixfon:fix/25453-kotlin-map-inline-enum-type

Conversation

@fixfon

@fixfon fixfon commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Description:

With the kotlin and kotlin-spring generators, an object property whose additionalProperties is an inline enum was typed as the nested enum (val lessonStatus: Today.LessonStatus) instead of a map of it. Such a property is flagged isEnum, and the data class property templates only special-cased arrays, so the Map was lost and decoding the JSON object failed.

The property templates now wrap the nested enum in a map when isMap is set, the same way lists of inline enums are already handled:

  • kotlin-client/data_class_req_var.mustache and data_class_opt_var.mustache: kotlin.collections.Map<kotlin.String, Today.LessonStatus> (MutableMap with modelMutable)
  • kotlin-spring/dataClassReqVar.mustache and dataClassOptVar.mustache: Map<kotlin.String, Today.LessonStatus>

Not addressed here: a map of lists or of maps of inline enums, the interface property templates, and nullable map values in kotlin-spring.

I added a test in KotlinClientCodegenModelTest and one in KotlinSpringServerCodegenTest with 3_0/kotlin/issue25453-map-of-inline-enum.yaml. Both fail without the change. samples/ has no diff.

Fixes #25453

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples (see below for what I ran instead):
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

What I ran on this branch (macOS, JDK 21, Maven wrapper):

  • ./mvnw -pl modules/openapi-generator -am test -Dtest=KotlinClientCodegenModelTest,KotlinClientCodegenApiTest,KotlinModelCodegenTest,KotlinSpringServerCodegenTest passes (436 tests, 0 failures, 4 skipped). With the four templates put back to master, the two new tests fail.
  • ./bin/generate-samples.sh with the 104 kotlin and kotlin-spring configs exits 0 and leaves samples/ unchanged.
  • I generated a jvm-retrofit2 kotlinx client from the issue spec and built it with its Gradle wrapper. With this change it compiles, and a small local test (not committed) decodes {"lessonStatus":{"l1":"ready","l2":"failed"}} and reads lessonStatus["l1"]. With master templates the same decode fails with JsonDecodingException ... at path: $.lessonStatus.
  • I generated the kotlin-spring server from the issue spec and compiled it with mvn compile on its generated pom.xml (its Gradle 8.1.1 wrapper does not run on JDK 21, with or without this change). The property is Map<String, Today.LessonStatus> with the change and Today.LessonStatus on master.

I did not run the full ./mvnw clean package, the other sample configs or ./bin/utils/export_docs_generators.sh, so the second box is unchecked. No option or docs text changed.

cc @karismann @Zomzog @andrewemery @4brunu @yutaka0m @stefankoppier @e5l


Summary by cubic

Fixes the kotlin and kotlin-spring generators emitting object properties whose additionalProperties is an inline enum as the bare nested enum instead of a Map, which broke JSON decoding.

Details

  • Data class property templates now emit kotlin.collections.Map<kotlin.String, ...> (or MutableMap with modelMutable in the kotlin client) when the property is an enum map, matching how lists of inline enums are handled.
  • Adds tests in both generators covering required, optional, and nullable map-of-inline-enum properties.
  • Not addressed: maps of lists or maps of inline enums, interface property templates, and nullable map values in kotlin-spring.

Fixes #25453.

Written for commit 5918977. Summary will update on new commits.

View guided diff

…is an inline enum

A map property whose additionalProperties is an inline enum is flagged isEnum, and the kotlin and kotlin-spring data class property templates only special-cased arrays, so it was emitted as the bare nested enum instead of a Map. The templates now wrap the nested enum in kotlin.collections.Map<kotlin.String, ...> (MutableMap with modelMutable in the kotlin client), the same way lists are already handled. The new tests cover both generators.

Fixes OpenAPITools#25453

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 7 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java">

<violation number="1" location="modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java:1609">
P3: The new test only checks the immutable `kotlin.collections.Map` output. The `MutableMap` branch added to the data class templates for `modelMutable` is not exercised, so a regression there would go unnoticed. Add a case with `mutable=true` asserting `kotlin.collections.MutableMap<kotlin.String, Today.LessonStatus>`.</violation>
</file>

Reply with feedback, questions, or to request a fix.

View guided diff | Re-trigger cubic

TestUtils.assertFileContains(modelKt, "val lessonStatus: kotlin.collections.Map<kotlin.String, Today.LessonStatus>");
TestUtils.assertFileContains(modelKt, "val previousStatus: kotlin.collections.Map<kotlin.String, Today.PreviousStatus>? = null");
TestUtils.assertFileContains(modelKt, "enum class LessonStatus(val value: kotlin.String)");
TestUtils.assertFileContains(modelKt, "enum class PreviousStatus(val value: kotlin.String)");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The new test only checks the immutable kotlin.collections.Map output. The MutableMap branch added to the data class templates for modelMutable is not exercised, so a regression there would go unnoticed. Add a case with mutable=true asserting kotlin.collections.MutableMap<kotlin.String, Today.LessonStatus>.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java, line 1609:

<comment>The new test only checks the immutable `kotlin.collections.Map` output. The `MutableMap` branch added to the data class templates for `modelMutable` is not exercised, so a regression there would go unnoticed. Add a case with `mutable=true` asserting `kotlin.collections.MutableMap<kotlin.String, Today.LessonStatus>`.</comment>

<file context>
@@ -1582,4 +1582,30 @@ public void testEnumUnknownDefaultCaseIsRegisteredAsCliOption() {
+        TestUtils.assertFileContains(modelKt, "val lessonStatus: kotlin.collections.Map<kotlin.String, Today.LessonStatus>");
+        TestUtils.assertFileContains(modelKt, "val previousStatus: kotlin.collections.Map<kotlin.String, Today.PreviousStatus>? = null");
+        TestUtils.assertFileContains(modelKt, "enum class LessonStatus(val value: kotlin.String)");
+        TestUtils.assertFileContains(modelKt, "enum class PreviousStatus(val value: kotlin.String)");
+    }
 }
</file context>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG][KOTLIN] Map with inline enum values (additionalProperties enum) is typed as the enum, not a Map

1 participant