Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/samples-kotlin-client.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ jobs:
- samples/client/petstore/kotlin-explicit
- samples/client/petstore/kotlin-gson
- samples/client/petstore/kotlin-jackson
- samples/client/petstore/kotlin-jackson3
- samples/client/petstore/kotlin-model-prefix-type-mappings
# needs Android configured
#- samples/client/petstore/kotlin-json-request-string
Expand Down
10 changes: 10 additions & 0 deletions bin/configs/kotlin-jackson3.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
generatorName: kotlin
outputDir: samples/client/petstore/kotlin-jackson3
inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/kotlin-client
additionalProperties:
serializationLibrary: jackson
useJackson3: "true"
artifactId: kotlin-petstore-jackson3
enumPropertyNaming: UPPERCASE
enumUnknownDefaultCase: "true"
10 changes: 10 additions & 0 deletions bin/configs/kotlin-jvm-spring-4-restclient-jackson3.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
generatorName: kotlin
outputDir: samples/client/petstore/kotlin-jvm-spring-4-restclient-jackson3
library: jvm-spring-restclient
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/kotlin-client
additionalProperties:
artifactId: kotlin-petstore-spring4-restclient-jackson3
enumUnknownDefaultCase: "true"
serializationLibrary: jackson
useSpringBoot4: "true"
3 changes: 2 additions & 1 deletion docs/generators/kotlin.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,13 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|sourceFolder|source folder for generated code| |src/main/kotlin|
|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|
|useCoroutines|Whether to use the Coroutines adapter with the retrofit2 library.| |false|
|useJackson3|Use Jackson 3 dependencies (tools.jackson package). Not yet supported for kotlin-client; reserved for future use.| |false|
|useJackson3|Use Jackson 3 dependencies (tools.jackson package). Requires serializationLibrary=jackson. Incompatible with openApiNullable.| |false|
|useNonAsciiHeaders|Allow to use non-ascii headers with the okhttp library| |false|
|useResponseAsReturnType|When using retrofit2 and coroutines, use `Response`<`T`> as return type instead of `T`.| |true|
|useRxJava3|Whether to use the RxJava3 adapter with the retrofit2 library.| |false|
|useSettingsGradle|Whether the project uses settings.gradle.| |false|
|useSpringBoot3|Whether to use the Spring Boot 3 with the jvm-spring-webclient library.| |false|
|useSpringBoot4|Use Spring Boot 4 with the jvm-spring-restclient or jvm-spring-webclient library. Implies useJackson3.| |false|

## SUPPORTED VENDOR EXTENSIONS

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
public static final String USE_SETTINGS_GRADLE = "useSettingsGradle";
public static final String IDEA = "idea";
public static final String USE_SPRING_BOOT3 = "useSpringBoot3";
public static final String USE_SPRING_BOOT4 = "useSpringBoot4";
public static final String USE_RESPONSE_AS_RETURN_TYPE = "useResponseAsReturnType";

public static final String DATE_LIBRARY = "dateLibrary";
Expand Down Expand Up @@ -271,6 +272,7 @@ public KotlinClientCodegen() {
cliOptions.add(CliOption.newBoolean(USE_RX_JAVA3, "Whether to use the RxJava3 adapter with the retrofit2 library."));
cliOptions.add(CliOption.newBoolean(USE_COROUTINES, "Whether to use the Coroutines adapter with the retrofit2 library."));
cliOptions.add(CliOption.newBoolean(USE_SPRING_BOOT3, "Whether to use the Spring Boot 3 with the jvm-spring-webclient library."));
cliOptions.add(CliOption.newBoolean(USE_SPRING_BOOT4, "Use Spring Boot 4 with the jvm-spring-restclient or jvm-spring-webclient library. Implies useJackson3."));
cliOptions.add(CliOption.newBoolean(OMIT_GRADLE_PLUGIN_VERSIONS, "Whether to declare Gradle plugin versions in build files."));
cliOptions.add(CliOption.newBoolean(OMIT_GRADLE_WRAPPER, "Whether to omit Gradle wrapper for creating a sub project."));
cliOptions.add(CliOption.newBoolean(USE_SETTINGS_GRADLE, "Whether the project uses settings.gradle."));
Expand Down Expand Up @@ -300,7 +302,7 @@ public KotlinClientCodegen() {
cliOptions.add(CliOption.newBoolean(USE_RESPONSE_AS_RETURN_TYPE, "When using retrofit2 and coroutines, use `Response`<`T`> as return type instead of `T`.", true));

cliOptions.add(CliOption.newBoolean(USE_JACKSON_3,
"Use Jackson 3 dependencies (tools.jackson package). Not yet supported for kotlin-client; reserved for future use."));
"Use Jackson 3 dependencies (tools.jackson package). Requires serializationLibrary=jackson. Incompatible with openApiNullable."));
}

@Override
Expand Down Expand Up @@ -469,9 +471,10 @@ public void processOpts() {
convertPropertyToBooleanAndWriteBack(USE_SPRING_BOOT3);
}

if (isUseJackson3()) {
throw new IllegalArgumentException(
"useJackson3 is not yet supported for kotlin-client. Jackson 3 support for kotlin-client will be added in a future release.");
if (additionalProperties.containsKey(USE_SPRING_BOOT4)) {
convertPropertyToBooleanAndWriteBack(USE_SPRING_BOOT4);
additionalProperties.put(USE_JACKSON_3, "true");
setUseJackson3(true);
}

if (additionalProperties.containsKey(CodegenConstants.SERIALIZATION_LIBRARY)) {
Expand All @@ -481,6 +484,16 @@ public void processOpts() {
additionalProperties.put(this.serializationLibrary.name(), true);
}

if (isUseJackson3()) {
if (this.serializationLibrary != SERIALIZATION_LIBRARY_TYPE.jackson) {
throw new IllegalArgumentException("useJackson3 requires serializationLibrary=jackson");
}
if (additionalProperties.containsKey("openApiNullable")
&& Boolean.parseBoolean(additionalProperties.get("openApiNullable").toString())) {
throw new IllegalArgumentException("openApiNullable cannot be set with useJackson3");
}
}

if (additionalProperties.containsKey(MAP_FILE_BINARY_TO_BYTE_ARRAY)) {
setMapFileBinaryToByteArray(convertPropertyToBooleanAndWriteBack(MAP_FILE_BINARY_TO_BYTE_ARRAY));
}
Expand Down Expand Up @@ -864,8 +877,9 @@ private void processJvmSpringWebClientLibrary(final String infrastructureFolder)
}

private void processJvmSpringRestClientLibrary(final String infrastructureFolder) {
if (additionalProperties.getOrDefault(USE_SPRING_BOOT3, false).equals(false)) {
throw new RuntimeException("This library must use Spring Boot 3. Try adding '--additional-properties useSpringBoot3=true' to your command.");
if (additionalProperties.getOrDefault(USE_SPRING_BOOT3, false).equals(false)
&& additionalProperties.getOrDefault(USE_SPRING_BOOT4, false).equals(false)) {
throw new RuntimeException("This library requires Spring Boot 3 or 4. Try adding '--additional-properties useSpringBoot3=true' or '--additional-properties useSpringBoot4=true' to your command.");
}

processJvmSpring(infrastructureFolder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,17 @@ buildscript {
ext.vertx_version = "5.0.4"
{{/jvm-vertx}}
{{#jvm-spring}}
{{#useSpringBoot4}}
ext.spring_boot_version = "4.0.1"
{{/useSpringBoot4}}
{{^useSpringBoot4}}
{{#useSpringBoot3}}
ext.spring_boot_version = "3.5.5"
{{/useSpringBoot3}}
{{^useSpringBoot3}}
ext.spring_boot_version = "2.7.18"
{{/useSpringBoot3}}
{{/useSpringBoot4}}
{{/jvm-spring}}
ext.spotless_version = "7.2.1"

Expand Down Expand Up @@ -163,8 +168,13 @@ dependencies {
{{/gson}}
{{#jackson}}
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
{{#useJackson3}}
implementation "tools.jackson.module:jackson-module-kotlin:3.0.1"
{{/useJackson3}}
{{^useJackson3}}
implementation "com.fasterxml.jackson.module:jackson-module-kotlin:2.20.0"
implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.20.0"
{{/useJackson3}}
{{/jackson}}
{{#kotlinx_serialization}}
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,24 @@ import kotlinx.datetime.LocalTime
import java.util.UUID
{{/gson}}
{{#jackson}}
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
{{^useJackson3}}
import {{jacksonPackage}}.databind.DeserializationFeature
import {{jacksonPackage}}.databind.ObjectMapper
import {{jacksonPackage}}.databind.SerializationFeature
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import {{jacksonPackage}}.module.kotlin.jacksonObjectMapper
{{/useJackson3}}
{{#useJackson3}}
import {{jacksonPackage}}.databind.DeserializationFeature
import {{jacksonPackage}}.databind.ObjectMapper
import {{jacksonPackage}}.databind.cfg.DateTimeFeature
{{#enumUnknownDefaultCase}}
import {{jacksonPackage}}.databind.cfg.EnumFeature
{{/enumUnknownDefaultCase}}
import com.fasterxml.jackson.annotation.JsonInclude
import {{jacksonPackage}}.module.kotlin.jsonMapper
import {{jacksonPackage}}.module.kotlin.kotlinModule
{{/useJackson3}}
{{/jackson}}
{{#kotlinx_serialization}}
import java.math.BigDecimal
Expand Down Expand Up @@ -120,6 +133,7 @@ import java.util.concurrent.atomic.AtomicLong
}
{{/gson}}
{{#jackson}}
{{^useJackson3}}
@JvmStatic
val jacksonObjectMapper: ObjectMapper = jacksonObjectMapper()
.findAndRegisterModules()
Expand All @@ -129,6 +143,24 @@ import java.util.concurrent.atomic.AtomicLong
{{/enumUnknownDefaultCase}}
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, {{failOnUnknownProperties}})
{{/useJackson3}}
{{#useJackson3}}
@JvmStatic
val jacksonObjectMapper: ObjectMapper = jsonMapper {
addModule(kotlinModule())
changeDefaultPropertyInclusion { it.withValueInclusion(JsonInclude.Include.NON_ABSENT) }
{{#enumUnknownDefaultCase}}
enable(EnumFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE)
{{/enumUnknownDefaultCase}}
disable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS)
{{#failOnUnknownProperties}}
enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
{{/failOnUnknownProperties}}
{{^failOnUnknownProperties}}
disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
{{/failOnUnknownProperties}}
}
{{/useJackson3}}
{{/jackson}}
{{#kotlinx_serialization}}
private var isAdaptersInitialized = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import com.google.gson.GsonBuilder
import java.text.DateFormat
{{/gson}}
{{#jackson}}
import com.fasterxml.jackson.databind.ObjectMapper
import {{jacksonPackage}}.databind.ObjectMapper
{{/jackson}}

{{#operations}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ import java.text.DateFormat
{{/gson}}
{{#jackson}}
import io.ktor.serialization.jackson.*
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import com.fasterxml.jackson.core.util.DefaultIndenter
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter
import {{jacksonPackage}}.module.kotlin.jacksonObjectMapper
import {{jacksonPackage}}.databind.ObjectMapper
import {{jacksonPackage}}.databind.SerializationFeature
{{^useJackson3}}
import {{jacksonPackage}}.datatype.jsr310.JavaTimeModule
{{/useJackson3}}
import {{jacksonPackage}}.core.util.DefaultIndenter
import {{jacksonPackage}}.core.util.DefaultPrettyPrinter
{{/jackson}}
import {{packageName}}.auth.*

Expand Down Expand Up @@ -96,7 +98,9 @@ import {{packageName}}.auth.*
indentArraysWith(DefaultPrettyPrinter.FixedSpaceIndenter.instance)
indentObjectsWith(DefaultIndenter(" ", "\n"))
})
{{^useJackson3}}
registerModule(JavaTimeModule())
{{/useJackson3}}
}
{{/jackson}}
protected val UNSAFE_HEADERS: List<String> = listOf(HttpHeaders.ContentType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ import org.threeten.bp.OffsetTime
import com.google.gson.reflect.TypeToken
{{/gson}}
{{#jackson}}
import com.fasterxml.jackson.core.type.TypeReference
import {{jacksonPackage}}.core.type.TypeReference
{{/jackson}}
{{#moshi}}
import com.squareup.moshi.adapter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import com.squareup.moshi.Moshi
import retrofit2.converter.moshi.MoshiConverterFactory
{{/moshi}}
{{#jackson}}
import com.fasterxml.jackson.databind.ObjectMapper
import {{jacksonPackage}}.databind.ObjectMapper
import retrofit2.converter.jackson.JacksonConverterFactory
{{/jackson}}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ import org.springframework.web.client.RestClient
import org.springframework.web.client.RestClientResponseException

{{#jackson}}
{{^useJackson3}}
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
{{/useJackson3}}
{{#useJackson3}}
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter
import {{packageName}}.infrastructure.Serializer
{{/useJackson3}}
{{/jackson}}
import org.springframework.http.ResponseEntity
import org.springframework.http.MediaType
Expand All @@ -23,11 +29,20 @@ import {{packageName}}.infrastructure.*
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}open {{/nonPublicApi}}class {{classname}}(client: RestClient) : ApiClient(client) {

{{#jackson}}
{{^useJackson3}}
{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}constructor(baseUrl: String) : this(RestClient.builder()
.baseUrl(baseUrl)
.messageConverters { it.add(MappingJackson2HttpMessageConverter()) }
.build()
)
{{/useJackson3}}
{{#useJackson3}}
{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}constructor(baseUrl: String) : this(RestClient.builder()
.baseUrl(baseUrl)
.configureMessageConverters { it.withJsonConverter(JacksonJsonHttpMessageConverter(Serializer.jacksonObjectMapper)) }
.build()
)
{{/useJackson3}}
{{/jackson}}

{{#operation}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import java.io.IOException

{{#jackson}}
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.core.type.TypeReference
import {{jacksonPackage}}.core.type.TypeReference
{{/jackson}}
{{#gson}}
import com.google.gson.reflect.TypeToken
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import io.vertx.core.Vertx
import io.vertx.core.buffer.Buffer
import java.nio.charset.StandardCharsets
{{#jackson}}
import com.fasterxml.jackson.core.type.TypeReference
import {{jacksonPackage}}.core.type.TypeReference
{{/jackson}}
{{#gson}}
import com.google.gson.reflect.TypeToken
Expand Down
Loading
Loading