[kotlin] Fix the kotlinx serializer for a number branch in oneOf/anyOf wrappers

FI
8h ago
+96-0

Description:

With the kotlin generator, serializationLibrary=kotlinx_serialization and generateOneOfAnyOfWrappers=true, an anyOf or oneOf with an unformatted type: number branch generated a wrapper whose serialize() did not compile. The branch fell through to the {{^isPrimitiveType}} case and wrote jsonEncoder.encodeSerializableValue(java.math.BigDecimal.serializer(), value.value), and BigDecimal has no serializer().

In kotlin-client/anyof_class.mustache and oneof_class.mustache that case now writes jsonEncoder.encodeJsonElement(JsonPrimitive(value.value)) when isNumber is set. Every other non-primitive branch keeps the line it had. The change is limited to type: number without a format.

I added a test in KotlinClientCodegenModelTest with 3_0/kotlin/issue25452-anyof-oneof-number.yaml, the spec from the issue. It checks the generated AnyOfValue.kt and OneOfValue.kt and fails without the change. samples/ has no diff.

Noticed while here: the {{#isNumber}}{{#isDouble}} and {{#isFloat}} branches in these two templates are never reached, because isNumber is not set for format: double or float. A Double or Float member (also via typeMappings) therefore gets no case in serialize(). This is not addressed in this PR.

Fixes #25452

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 passes (70 tests). With the two templates put back to master, the new test fails.

  • ./mvnw -pl modules/openapi-generator -am test -Dtest=KotlinClientCodegenModelTest,KotlinClientCodegenApiTest,KotlinModelCodegenTest,KotlinJvmVolleyModelCodegenTest passes (127 tests, 0 failures, 4 skipped).

  • I generated a jvm-retrofit2 client from the issue spec with the options above and built it with its own Gradle wrapper (./gradlew compileKotlin). With master templates it fails with Unresolved reference 'serializer' in AnyOfValue.kt and OneOfValue.kt. With this change, BUILD SUCCESSFUL.

  • ./bin/generate-samples.sh with the four kotlin-oneOf-*-kotlinx-serialization* configs exits 0 and leaves samples/ unchanged.

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 client code generator for oneOf/anyOf wrappers when a branch is an unformatted type: number, so the generated kotlinx_serialization code compiles instead of failing with an unresolvable BigDecimal.serializer() reference.

  • The number branch in anyof_class.mustache and oneof_class.mustache now writes the value as a JSON number via JsonPrimitive and deserializes it from a non-string JsonPrimitive content as BigDecimal.
  • Adds a test with a new OpenAPI spec that verifies the generated wrappers avoid BigDecimal.serializer() and decodeFromJsonElement<java.math.BigDecimal>.