fix(kotlin-client): use escaped propertyBaseName for JsonClassDiscriminator

Merged
RA
2mo ago
+3764-2

Fixes #22523

Problem

The kotlinx_serialization and multiplatform templates in kotlin-client/data_class.mustache emitted discriminator.propertyName. DefaultCodegen sets that field through toVarName() (DefaultCodegen.java:3770), so it is a sanitized Kotlin identifier rather than the wire-format name — a discriminator declared as $type was emitted as dollarType.

This left the generated client internally inconsistent. oneof_class.mustache already writes and reads the discriminator using propertyBaseName (lines 142, 154), and typeInfoAnnotation.mustache uses propertyBaseName in kotlin-client, kotlin-server, and kotlin-spring. These two annotation lines were the only remaining uses of propertyName.

Fix

Switch both lines to propertyBaseName, wrapped in lambda.escapeDollar — the same lambda already used ~40 times in this file for baseName — because the raw name lands inside a Kotlin string literal, where an unescaped $ begins an interpolation.

Verification

Same spec, same command, only the template differs:

templategenerated
beforediscriminator = "dollarType"
propertyBaseName alonediscriminator = "$type" — correct name, does not compile
propertyBaseName + escapeDollardiscriminator = "\$type" — correct and compiles

./gradlew compileKotlin passes on the generated kotlin-allOf-special-discriminator-kotlinx-serialization sample.

Regenerating all bin/configs/kotlin-*.yaml produces no diff in existing samples — every current spec uses a discriminator that is already a valid identifier, so toVarName() was a no-op there.

New samples

Adds polymorphism-special-discriminator.yaml (a copy of the existing polymorphism.yaml with a $type discriminator) plus two configs covering both affected templates, giving CI a regression case.

Relation to #23633

That draft addresses Kotlin escaping broadly but is currently blocked on build failures. This is a narrow, independent fix for the discriminator case only.

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

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Summary by cubic

Fixes Kotlin client generation for polymorphic discriminators when using kotlinx-serialization and the multiplatform library. Previously, @JsonClassDiscriminator used a transformed name (e.g., $type -> dollarType), which disagreed with oneof_class.mustache and broke serialization; now it uses the raw discriminator name with escaped dollars. Fixes #22523.

  • Update modules/openapi-generator/src/main/resources/kotlin-client/data_class.mustache to use discriminator.propertyBaseName wrapped with lambda.escapeDollar in both kotlinx_serialization and multiplatform paths.
  • Add a test spec with a $type discriminator and generate samples for kotlinx-serialization and multiplatform to validate the fix.