Skip to content

[kotlin][client] Support useJackson3 for the jvm-ktor library - #25639

Open
denysgaievskyi wants to merge 2 commits into
OpenAPITools:masterfrom
denysgaievskyi:kotlin-jvm-ktor-jackson3
Open

denysgaievskyi wants to merge 2 commits into
OpenAPITools:masterfrom
denysgaievskyi:kotlin-jvm-ktor-jackson3

Conversation

@denysgaievskyi

@denysgaievskyi denysgaievskyi commented Nov 12, 2026 •

Copy link
Copy Markdown

This extends the approach of #24709 (Jackson 3 for jvm-okhttp4 and jvm-spring-restclient) to the jvm-ktor library.

Today the codegen rejects useJackson3 for jvm-ktor, and the jvm-ktor templates hard-code Jackson 2 (com.fasterxml.jackson) in ApiClient and in the API classes.

Changes:

  • KotlinClientCodegen: allow useJackson3 with library=jvm-ktor.
  • jvm-ktor/infrastructure/ApiClient.kt.mustache and jvm-ktor/api.mustache: with useJackson3, the generated code imports tools.jackson and io.ktor.serialization.jackson3, and jsonBlock becomes JsonMapper.Builder.() -> Unit. Jackson 3 mappers are immutable and configured through a builder, so the parameter type changes. JavaTimeModule is not registered, because Jackson 3 databind supports java.time itself.
  • build.gradle.mustache: with useJackson3, jvm-ktor depends on ktor-serialization-jackson3 instead of ktor-client-jackson and ktor-serialization-jackson.
  • New sample samples/client/petstore/kotlin-jvm-ktor-jackson3, added to the Kotlin client samples workflow.
  • Tests for the Jackson 3 output and for the unchanged Jackson 2 default.

Without useJackson3, the generated code does not change.

Note for users who switch: the Jackson 2 JSON_DEFAULT writes OffsetDateTime as an epoch number, because WRITE_DATES_AS_TIMESTAMPS is on by default in Jackson 2. Jackson 3 writes ISO-8601 strings by default, which matches format: date-time.

Tested:

  • KotlinClientCodegenModelTest and KotlinClientCodegenApiTest: 111 tests, 0 failures.
  • ./bin/generate-samples.sh bin/configs/kotlin* (130 configs): the only output change is the new sample.
  • ./bin/utils/export_docs_generators.sh: no change.
  • ./gradlew build -x test in the new sample: passes.
  • A client generated from a larger real-world spec with these templates compiles against Jackson 3.3.0 and ktor 3.6.1 and made a successful live GET request.

Notes on the automated review:

  • The new sample's docs/ is identical to the existing kotlin-jvm-ktor-jackson sample (diff -r is empty). The doc-example issues come from the shared jvm-ktor docs templates, which this PR does not change.
  • The new sample is in the default (Java 11) matrix, like kotlin-jackson3 and kotlin-jvm-spring-4-restclient-jackson3. The CI step compiles only (./gradlew build -x test), and those samples pass there on master. I can move all three to a Java 17 entry if you prefer.

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples. I built with ./mvnw install -DskipTests plus the Kotlin codegen tests above, and regenerated only the Kotlin samples (bin/configs/kotlin*), because only Kotlin templates changed:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    Commit all changed files.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

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

The jvm-ktor templates hard-coded Jackson 2 (com.fasterxml.jackson) in
ApiClient and the API classes, and the codegen rejected useJackson3 for
this library. This follows the approach of OpenAPITools#24709 for jvm-okhttp4 and
jvm-spring-restclient:

- allow useJackson3 with library jvm-ktor
- ApiClient/api templates: with useJackson3, import tools.jackson and
  io.ktor.serialization.jackson3, and take jsonBlock as
  JsonMapper.Builder.() -> Unit (Jackson 3 mappers are immutable and
  configured through a builder). JavaTimeModule is dropped: java.time
  support is built into Jackson 3 databind.
- build.gradle: with useJackson3, depend on ktor-serialization-jackson3
  instead of ktor-client-jackson and ktor-serialization-jackson.
- new sample kotlin-jvm-ktor-jackson3, added to the Kotlin client
  samples workflow.
- tests for the Jackson 3 output and for the unchanged Jackson 2 default.

Without useJackson3 the generated code is unchanged.

@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.

All reported issues were addressed across 54 files

Reply to a comment to ask cubic a question or push back. It learns from your replies.

View guided diff | Re-trigger cubic

@AndreyVMarkelov AndreyVMarkelov 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.

The tests and sample build pass, but Jackson 3 fails at runtime on Java 11. Could we use Java 17 for this sample and add a simple JSON serialization/deserialization test? CI currently skips tests with -x test.

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.

2 participants