Skip to content

Commit 4535b51

Browse files
committed
feat(kotlin-client): add Jackson 3 support with useJackson3 option
Wire the existing AbstractKotlinCodegen Jackson 3 infrastructure into the kotlin client generator. When useJackson3=true (requires serializationLibrary=jackson), all templates use the tools.jackson package instead of com.fasterxml.jackson, and build.gradle pulls jackson-module-kotlin 3.0.1 without the separate JSR-310 module. - Register useJackson3 CLI option in KotlinClientCodegen - Add validation: requires jackson serialization, incompatible with openApiNullable - Replace hardcoded com.fasterxml.jackson with {{jacksonPackage}} in all model, serializer, and library-specific templates - Make JavaTimeModule conditional (not needed in Jackson 3) for jvm-ktor - Add Jackson 3 dependency block in build.gradle.mustache - Add tests for validation and generated output - Add kotlin-jackson3 sample config and generated sample - Add sample to CI workflow matrix - Regenerate generator docs
1 parent c085974 commit 4535b51

File tree

68 files changed

+5010
-38
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+5010
-38
lines changed

.github/workflows/samples-kotlin-client.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ jobs:
2626
- samples/client/petstore/kotlin-explicit
2727
- samples/client/petstore/kotlin-gson
2828
- samples/client/petstore/kotlin-jackson
29+
- samples/client/petstore/kotlin-jackson3
2930
- samples/client/petstore/kotlin-model-prefix-type-mappings
3031
# needs Android configured
3132
#- samples/client/petstore/kotlin-json-request-string

bin/configs/kotlin-jackson3.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
generatorName: kotlin
2+
outputDir: samples/client/petstore/kotlin-jackson3
3+
inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore.yaml
4+
templateDir: modules/openapi-generator/src/main/resources/kotlin-client
5+
additionalProperties:
6+
serializationLibrary: jackson
7+
useJackson3: "true"
8+
artifactId: kotlin-petstore-jackson3
9+
enumPropertyNaming: UPPERCASE
10+
enumUnknownDefaultCase: "true"

docs/generators/kotlin.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
4949
|sourceFolder|source folder for generated code| |src/main/kotlin|
5050
|supportAndroidApiLevel25AndBelow|[WARNING] This flag will generate code that has a known security vulnerability. It uses `kotlin.io.createTempFile` instead of `java.nio.file.Files.createTempFile` in order to support Android API level 25 and below. For more info, please check the following links https://github.com/OpenAPITools/openapi-generator/security/advisories/GHSA-23x4-m842-fmwf, https://github.com/OpenAPITools/openapi-generator/pull/9284| |false|
5151
|useCoroutines|Whether to use the Coroutines adapter with the retrofit2 library.| |false|
52+
|useJackson3|Use Jackson 3 dependencies (tools.jackson package). Requires serializationLibrary=jackson. Incompatible with openApiNullable.| |false|
5253
|useNonAsciiHeaders|Allow to use non-ascii headers with the okhttp library| |false|
5354
|useResponseAsReturnType|When using retrofit2 and coroutines, use `Response`<`T`> as return type instead of `T`.| |true|
5455
|useRxJava3|Whether to use the RxJava3 adapter with the retrofit2 library.| |false|

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
5656

5757
public static final String JAVAX_PACKAGE = "javaxPackage";
5858
public static final String USE_JAKARTA_EE = "useJakartaEe";
59+
public static final String USE_JACKSON_3 = "useJackson3";
60+
public static final String JACKSON2_PACKAGE = "com.fasterxml.jackson";
61+
public static final String JACKSON3_PACKAGE = "tools.jackson";
62+
public static final String JACKSON_PACKAGE = "jacksonPackage";
5963
public static final String SCHEMA_IMPLEMENTS = "schemaImplements";
6064
public static final String SCHEMA_IMPLEMENTS_FIELDS = "schemaImplementsFields";
6165
public static final String X_KOTLIN_IMPLEMENTS_SKIP = "xKotlinImplementsSkip";
@@ -80,6 +84,7 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
8084
protected boolean serializableModel = false;
8185

8286
@Setter protected boolean useJakartaEe = false;
87+
@Getter @Setter protected boolean useJackson3 = false;
8388

8489
@Setter protected boolean nonPublicApi = false;
8590

@@ -569,6 +574,17 @@ public void processOpts() {
569574
} else {
570575
applyJavaxPackage();
571576
}
577+
578+
if (additionalProperties.containsKey(USE_JACKSON_3)) {
579+
setUseJackson3(Boolean.parseBoolean(additionalProperties.get(USE_JACKSON_3).toString()));
580+
}
581+
additionalProperties.put(USE_JACKSON_3, useJackson3);
582+
583+
if (useJackson3) {
584+
applyJackson3Package();
585+
} else {
586+
applyJackson2Package();
587+
}
572588
}
573589

574590
protected boolean isModelMutable() {
@@ -844,6 +860,14 @@ protected void applyJakartaPackage() {
844860
writePropertyBack(JAVAX_PACKAGE, "jakarta");
845861
}
846862

863+
protected void applyJackson2Package() {
864+
writePropertyBack(JACKSON_PACKAGE, JACKSON2_PACKAGE);
865+
}
866+
867+
protected void applyJackson3Package() {
868+
writePropertyBack(JACKSON_PACKAGE, JACKSON3_PACKAGE);
869+
}
870+
847871
@Override
848872
protected boolean isReservedWord(String word) {
849873
// We want case-sensitive escaping, to avoid unnecessary backtick-escaping.

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,9 @@ public KotlinClientCodegen() {
293293

294294
cliOptions.add(CliOption.newBoolean(USE_NON_ASCII_HEADERS, "Allow to use non-ascii headers with the okhttp library"));
295295
cliOptions.add(CliOption.newBoolean(USE_RESPONSE_AS_RETURN_TYPE, "When using retrofit2 and coroutines, use `Response`<`T`> as return type instead of `T`.", true));
296+
297+
cliOptions.add(CliOption.newBoolean(USE_JACKSON_3,
298+
"Use Jackson 3 dependencies (tools.jackson package). Requires serializationLibrary=jackson. Incompatible with openApiNullable."));
296299
}
297300

298301
@Override
@@ -464,6 +467,16 @@ public void processOpts() {
464467
additionalProperties.put(this.serializationLibrary.name(), true);
465468
}
466469

470+
if (isUseJackson3()) {
471+
if (this.serializationLibrary != SERIALIZATION_LIBRARY_TYPE.jackson) {
472+
throw new IllegalArgumentException("useJackson3 requires serializationLibrary=jackson");
473+
}
474+
if (additionalProperties.containsKey("openApiNullable")
475+
&& Boolean.parseBoolean(additionalProperties.get("openApiNullable").toString())) {
476+
throw new IllegalArgumentException("openApiNullable cannot be set with useJackson3");
477+
}
478+
}
479+
467480
if (additionalProperties.containsKey(MAP_FILE_BINARY_TO_BYTE_ARRAY)) {
468481
setMapFileBinaryToByteArray(convertPropertyToBooleanAndWriteBack(MAP_FILE_BINARY_TO_BYTE_ARRAY));
469482
}

modules/openapi-generator/src/main/resources/kotlin-client/anyof_class.mustache

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ import com.squareup.moshi.JsonClass
1818
{{/moshi}}
1919
{{#jackson}}
2020
{{#enumUnknownDefaultCase}}
21-
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue
21+
import {{jacksonPackage}}.annotation.JsonEnumDefaultValue
2222
{{/enumUnknownDefaultCase}}
23-
import com.fasterxml.jackson.annotation.JsonProperty
23+
import {{jacksonPackage}}.annotation.JsonProperty
2424
{{#discriminator}}
25-
import com.fasterxml.jackson.annotation.JsonSubTypes
26-
import com.fasterxml.jackson.annotation.JsonTypeInfo
25+
import {{jacksonPackage}}.annotation.JsonSubTypes
26+
import {{jacksonPackage}}.annotation.JsonTypeInfo
2727
{{/discriminator}}
2828
{{/jackson}}
2929
{{#kotlinx_serialization}}

modules/openapi-generator/src/main/resources/kotlin-client/build.gradle.mustache

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,13 @@ dependencies {
163163
{{/gson}}
164164
{{#jackson}}
165165
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
166+
{{#useJackson3}}
167+
implementation "tools.jackson.module:jackson-module-kotlin:3.0.1"
168+
{{/useJackson3}}
169+
{{^useJackson3}}
166170
implementation "com.fasterxml.jackson.module:jackson-module-kotlin:2.20.0"
167171
implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.20.0"
172+
{{/useJackson3}}
168173
{{/jackson}}
169174
{{#kotlinx_serialization}}
170175
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0"

modules/openapi-generator/src/main/resources/kotlin-client/data_class.mustache

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ import com.squareup.moshi.JsonClass
1919
{{/moshi}}
2020
{{#jackson}}
2121
{{#enumUnknownDefaultCase}}
22-
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue
22+
import {{jacksonPackage}}.annotation.JsonEnumDefaultValue
2323
{{/enumUnknownDefaultCase}}
24-
import com.fasterxml.jackson.annotation.JsonProperty
24+
import {{jacksonPackage}}.annotation.JsonProperty
2525
{{#discriminator}}
26-
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
27-
import com.fasterxml.jackson.annotation.JsonSubTypes
28-
import com.fasterxml.jackson.annotation.JsonTypeInfo
26+
import {{jacksonPackage}}.annotation.JsonIgnoreProperties
27+
import {{jacksonPackage}}.annotation.JsonSubTypes
28+
import {{jacksonPackage}}.annotation.JsonTypeInfo
2929
{{/discriminator}}
3030
{{/jackson}}
3131
{{#kotlinx_serialization}}

modules/openapi-generator/src/main/resources/kotlin-client/enum_class.mustache

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ import com.squareup.moshi.Json
77
import com.squareup.moshi.JsonClass
88
{{/moshi}}
99
{{#jackson}}
10-
import com.fasterxml.jackson.annotation.JsonCreator
10+
import {{jacksonPackage}}.annotation.JsonCreator
1111
{{#enumUnknownDefaultCase}}
12-
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue
12+
import {{jacksonPackage}}.annotation.JsonEnumDefaultValue
1313
{{/enumUnknownDefaultCase}}
14-
import com.fasterxml.jackson.annotation.JsonProperty
15-
import com.fasterxml.jackson.annotation.JsonValue
14+
import {{jacksonPackage}}.annotation.JsonProperty
15+
import {{jacksonPackage}}.annotation.JsonValue
1616
import kotlin.jvm.JvmStatic
1717
{{/jackson}}
1818
{{#kotlinx_serialization}}

modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/Serializer.kt.mustache

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ import kotlinx.datetime.LocalTime
3030
import java.util.UUID
3131
{{/gson}}
3232
{{#jackson}}
33-
import com.fasterxml.jackson.databind.DeserializationFeature
34-
import com.fasterxml.jackson.databind.ObjectMapper
35-
import com.fasterxml.jackson.databind.SerializationFeature
36-
import com.fasterxml.jackson.annotation.JsonInclude
37-
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
33+
import {{jacksonPackage}}.databind.DeserializationFeature
34+
import {{jacksonPackage}}.databind.ObjectMapper
35+
import {{jacksonPackage}}.databind.SerializationFeature
36+
import {{jacksonPackage}}.annotation.JsonInclude
37+
import {{jacksonPackage}}.module.kotlin.jacksonObjectMapper
3838
{{/jackson}}
3939
{{#kotlinx_serialization}}
4040
import java.math.BigDecimal

0 commit comments

Comments
 (0)