Skip to content

[kotlin-client] Add decodeOrNull helper for Jackson enums, fix decode KDoc#23823

Open
limoneren wants to merge 1 commit into
OpenAPITools:masterfrom
limoneren:kotlin-decode-or-null
Open

[kotlin-client] Add decodeOrNull helper for Jackson enums, fix decode KDoc#23823
limoneren wants to merge 1 commit into
OpenAPITools:masterfrom
limoneren:kotlin-decode-or-null

Conversation

@limoneren
Copy link
Copy Markdown
Contributor

@limoneren limoneren commented May 19, 2026

PR checklist

  • Read the contribution guidelines.
  • Pull Request title clearly describes the work in the pull request and Pull Request description provides details about how to validate the work. Missing information here may result in delayed response from the community.
  • 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
    
    Only the Jackson-using Kotlin client samples that actually contain @JsonCreator enums were affected (the two echo-api samples). All other generators produce identical output. No docs changed.
  • File the PR against the correct branch: master (upcoming 7.x.0 minor release - breaking changes with fallbacks).
  • References issue using GitHub linking syntax.
  • @-mention Kotlin technical committee: @karismann @Zomzog @andrewemery @4brunu @yutaka0m @stefankoppier @e5l

Summary

Follow-up to #22663 (which fixed the 7.18.0 silent-null regression in Jackson deserialization of Kotlin enums). Addresses concerns raised in #23791.

PR #22535 (7.18.0) tied two contracts together by adding @JsonCreator to the existing decode() helper:

  1. decode() as a standalone function — historically nullable-returning, KDoc said "null otherwise."
  2. Jackson deserialization — pre-7.18.0 it used Jackson's default handling, which throws on unknown values.

PR #22663 (7.19.0) restored the Jackson throwing behavior, but as a side effect changed decode()'s direct-call contract for non-nullable enums (it now throws instead of returning null).

This PR cleanly separates the two contracts by adding decodeOrNull() alongside decode() in the Jackson branch:

  • decode() — strict, @JsonCreator entry point (unchanged from 7.19.0)
  • decodeOrNull() — lenient helper for manual callers; always returns null on unknown values or null input

This follows idiomatic Kotlin conventions (toIntOrNull, firstOrNull, etc.) and gives anyone affected by the 7.19.0 change a trivial one-line migration: MyEnum.decode(x)MyEnum.decodeOrNull(x).

Also corrects the KDoc on decode() which still claimed "null otherwise" even though the function now throws.

Changes

  • modules/openapi-generator/src/main/resources/kotlin-client/enum_class.mustache: adds decodeOrNull() in the Jackson branch; updates the decode() KDoc so it no longer says "null otherwise" when the function may throw.
  • KotlinClientCodegenModelTest.java: new unit test testJacksonEnumsExposeDecodeOrNullHelper verifying decodeOrNull is generated and @JsonCreator is still applied only to decode.
  • Regenerated affected Kotlin samples (kotlin-jvm-spring-3-restclient and kotlin-jvm-spring-3-webclient echo-api samples — the only samples containing Jackson-annotated Kotlin enums).

Validation

./mvnw -pl modules/openapi-generator test -Dtest='KotlinClientCodegenModelTest'
# Tests run: 45, Failures: 0, Errors: 0, Skipped: 0

Resolves #23791


Summary by cubic

Add decodeOrNull() to Kotlin Jackson enums to restore a lenient, null-returning lookup for manual calls, while keeping decode() as the strict @JsonCreator entry point. Also fixes decode() KDoc and adds a test; regenerated the affected echo-api Kotlin samples.

  • New Features

    • Added decodeOrNull() in the Jackson enum template; returns null for unknown or null input.
    • decode() remains strict (@JsonCreator) and throws on unknown values; Jackson uses this path.
    • Added a unit test to verify decodeOrNull() generation and that only decode() has @JsonCreator.
    • Regenerated echo-api Kotlin samples (Spring 3 RestClient/WebClient).
  • Bug Fixes

    • Corrected decode() KDoc to reflect its throwing behavior.

Written for commit ec18c9e. Summary will update on new commits. Review in cubic

… KDoc (OpenAPITools#23791)

Splits the two contracts that PR OpenAPITools#22535 (7.18.0) conflated:

- decode() stays strict and Jackson-bound (@JsonCreator entry point)
- decodeOrNull() is added as a lenient counterpart for direct callers
  that prefer the pre-7.19.0 null-on-unknown behavior

This gives users impacted by the 7.19.0 change a trivial migration path
(MyEnum.decode(x) -> MyEnum.decodeOrNull(x)) without giving up the
Jackson safety fix or matching the kotlin-spring/Java client behavior.

Also corrects the KDoc on decode() which still claimed "null otherwise"
even though the function now throws.
Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

No issues found across 4 files

Re-trigger cubic

@wing328
Copy link
Copy Markdown
Member

wing328 commented May 20, 2026

thanks for the PR

if no further question/feedback, i'll merge it later this week

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG][Kotlin] @JsonCreator decode() in non-nullable enums throws on unknown values instead of returning null (regression in 7.19.0)

2 participants