Skip to content
Merged
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 @@ -20,6 +20,7 @@ jobs:
sample:
# client
- samples/client/petstore/kotlin
- samples/client/petstore/kotlin-explicit
- samples/client/petstore/kotlin-gson
- samples/client/petstore/kotlin-jackson
- samples/client/petstore/kotlin-model-prefix-type-mappings
Expand Down
7 changes: 7 additions & 0 deletions bin/configs/kotlin-explicit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
generatorName: kotlin
outputDir: samples/client/petstore/kotlin-explicit
inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/kotlin-client
additionalProperties:
artifactId: kotlin-petstore-explicit
explicitApi: "true"
2 changes: 2 additions & 0 deletions docs/generators/kotlin.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|collectionType|Option. Collection type to use|<dl><dt>**array**</dt><dd>kotlin.Array</dd><dt>**list**</dt><dd>kotlin.collections.List</dd></dl>|list|
|dateLibrary|Option. Date library to use|<dl><dt>**threetenbp-localdatetime**</dt><dd>Threetenbp - Backport of JSR310 (jvm only, for legacy app only)</dd><dt>**kotlinx-datetime**</dt><dd>kotlinx-datetime (preferred for multiplatform)</dd><dt>**string**</dt><dd>String</dd><dt>**java8-localdatetime**</dt><dd>Java 8 native JSR310 (jvm only, for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (jvm only, preferred for jdk 1.8+)</dd><dt>**threetenbp**</dt><dd>Threetenbp - Backport of JSR310 (jvm only, preferred for jdk &lt; 1.8)</dd></dl>|java8|
|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |original|
|explicitApi|Generates code with explicit access modifiers to comply with Kotlin Explicit API Mode.| |false|
|failOnUnknownProperties|Fail Jackson de-serialization on unknown properties| |false|
|generateOneOfAnyOfWrappers|Generate oneOf, anyOf schemas as wrappers.| |false|
|generateRoomModels|Generate Android Room database models in addition to API models (JVM Volley library only)| |false|
Expand All @@ -34,6 +35,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|mapFileBinaryToByteArray|Map File and Binary to ByteArray (default: false)| |false|
|modelMutable|Create mutable models| |false|
|moshiCodeGen|Whether to enable codegen with the Moshi library. Refer to the [official Moshi doc](https://github.com/square/moshi#codegen) for more info.| |false|
|nonPublicApi|Generates code with reduced access modifiers; allows embedding elsewhere without exposing non-public API calls to consumers.| |false|
|nullableReturnType|Nullable return type| |false|
|omitGradlePluginVersions|Whether to declare Gradle plugin versions in build files.| |false|
|omitGradleWrapper|Whether to omit Gradle wrapper for creating a sub project.| |false|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {

public static final String MOSHI_CODE_GEN = "moshiCodeGen";

public static final String EXPLICIT_API = "explicitApi";
public static final String NULLABLE_RETURN_TYPE = "nullableReturnType";

public static final String SUPPORT_ANDROID_API_LEVEL_25_AND_BELLOW = "supportAndroidApiLevel25AndBelow";
Expand Down Expand Up @@ -268,6 +269,8 @@ public KotlinClientCodegen() {
cliOptions.add(CliOption.newBoolean(MOSHI_CODE_GEN, "Whether to enable codegen with the Moshi library. Refer to the [official Moshi doc](https://github.com/square/moshi#codegen) for more info."));
cliOptions.add(CliOption.newBoolean(FAIL_ON_UNKNOWN_PROPERTIES, "Fail Jackson de-serialization on unknown properties", false));

cliOptions.add(CliOption.newBoolean(EXPLICIT_API, "Generates code with explicit access modifiers to comply with Kotlin Explicit API Mode."));
cliOptions.add(CliOption.newBoolean(CodegenConstants.NON_PUBLIC_API, CodegenConstants.NON_PUBLIC_API_DESC));
cliOptions.add(CliOption.newBoolean(NULLABLE_RETURN_TYPE, "Nullable return type"));

cliOptions.add(CliOption.newBoolean(GENERATE_ROOM_MODELS, "Generate Android Room database models in addition to API models (JVM Volley library only)", false));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ import java.io.IOException
@Deprecated(message = "This schema is deprecated.")
{{/isDeprecated}}
{{>additionalModelTypeAnnotations}}
{{#nonPublicApi}}internal {{/nonPublicApi}}data class {{classname}}(var actualInstance: Any? = null) {
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}data class {{classname}}(var actualInstance: Any? = null) {

class CustomTypeAdapterFactory : TypeAdapterFactory {
override fun <T> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ idea {
}
}
{{/idea}}
{{#explicitApi}}
kotlin {
explicitApi()
}
{{/explicitApi}}
{{#jvm-spring-webclient}}{{#useSpringBoot3}}
kotlin {
jvmToolchain {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ import {{packageName}}.infrastructure.ITransformForStorage
{{#vendorExtensions.x-class-extra-annotation}}
{{{vendorExtensions.x-class-extra-annotation}}}
{{/vendorExtensions.x-class-extra-annotation}}
{{#nonPublicApi}}internal {{/nonPublicApi}}{{#discriminator}}interface{{/discriminator}}{{^discriminator}}{{#hasVars}}data {{/hasVars}}class{{/discriminator}} {{classname}}{{^discriminator}} (
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}{{#discriminator}}interface{{/discriminator}}{{^discriminator}}{{#hasVars}}data {{/hasVars}}class{{/discriminator}} {{classname}}{{^discriminator}} (

{{#allVars}}
{{#required}}{{>data_class_req_var}}{{/required}}{{^required}}{{>data_class_opt_var}}{{/required}}{{^-last}},{{/-last}}
Expand All @@ -94,7 +94,7 @@ import {{packageName}}.infrastructure.ITransformForStorage
){{/discriminator}}
{{/generateRoomModels}}
{{#serializableModel}}
{{#nonPublicApi}}internal {{/nonPublicApi}}companion object {
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}companion object {
private const val serialVersionUID: Long = 123
}
{{/serializableModel}}
Expand All @@ -120,7 +120,7 @@ import {{packageName}}.infrastructure.ITransformForStorage
{{#multiplatform}}
@Serializable
{{/multiplatform}}
{{#nonPublicApi}}internal {{/nonPublicApi}}enum class {{{nameInPascalCase}}}(val value: {{^isContainer}}{{dataType}}{{/isContainer}}{{#isContainer}}kotlin.String{{/isContainer}}) {
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}enum class {{{nameInPascalCase}}}({{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}val value: {{^isContainer}}{{dataType}}{{/isContainer}}{{#isContainer}}kotlin.String{{/isContainer}}) {
{{#allowableValues}}
{{#enumVars}}
{{^multiplatform}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import kotlinx.serialization.*
@JsonClass(generateAdapter = false)
{{/moshi}}
{{/multiplatform}}
{{#nonPublicApi}}internal {{/nonPublicApi}}enum class {{classname}}(val value: {{{dataType}}}) {
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}enum class {{classname}}({{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}val value: {{{dataType}}}) {
{{#allowableValues}}{{#enumVars}}
{{^multiplatform}}
{{#moshi}}
Expand Down Expand Up @@ -79,16 +79,16 @@ import kotlinx.serialization.*
*/
override fun toString(): kotlin.String = value{{^isString}}.toString(){{/isString}}

companion object {
{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}companion object {
/**
* Converts the provided [data] to a [String] on success, null otherwise.
*/
fun encode(data: kotlin.Any?): kotlin.String? = if (data is {{classname}}) "$data" else null
{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}fun encode(data: kotlin.Any?): kotlin.String? = if (data is {{classname}}) "$data" else null

/**
* Returns a valid [{{classname}}] for [data], null otherwise.
*/
fun decode(data: kotlin.Any?): {{classname}}? = data?.let {
{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}fun decode(data: kotlin.Any?): {{classname}}? = data?.let {
val normalizedData = "$it".lowercase()
values().firstOrNull { value ->
it == value || normalizedData == "$value".lowercase()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
package {{packageName}}.infrastructure

{{#nonPublicApi}}internal {{/nonPublicApi}}typealias MultiValueMap = MutableMap<String,List<String>>
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}typealias MultiValueMap = MutableMap<String,List<String>>

{{#nonPublicApi}}internal {{/nonPublicApi}}fun collectionDelimiter(collectionFormat: String) = when(collectionFormat) {
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}fun collectionDelimiter(collectionFormat: String): String = when(collectionFormat) {
"csv" -> ","
"tsv" -> "\t"
"pipe" -> "|"
"space" -> " "
else -> ""
}

{{#nonPublicApi}}internal {{/nonPublicApi}}val defaultMultiValueConverter: (item: Any?) -> String = { item -> "$item" }
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}val defaultMultiValueConverter: (item: Any?) -> String = { item -> "$item" }

{{#nonPublicApi}}internal {{/nonPublicApi}}fun <T : Any?> toMultiValue(items: Array<T>, collectionFormat: String, map: (item: T) -> String = defaultMultiValueConverter)
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}fun <T : Any?> toMultiValue(items: Array<T>, collectionFormat: String, map: (item: T) -> String = defaultMultiValueConverter): List<String>
= toMultiValue(items.asIterable(), collectionFormat, map)

{{#nonPublicApi}}internal {{/nonPublicApi}}fun <T : Any?> toMultiValue(items: Iterable<T>, collectionFormat: String, map: (item: T) -> String = defaultMultiValueConverter): List<String> {
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}fun <T : Any?> toMultiValue(items: Iterable<T>, collectionFormat: String, map: (item: T) -> String = defaultMultiValueConverter): List<String> {
return when(collectionFormat) {
"multi" -> items.map(map)
else -> listOf(items.joinToString(separator = collectionDelimiter(collectionFormat), transform = map))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package {{packageName}}.infrastructure
* NOTE: Headers is a Map<String,String> because rfc2616 defines
* multi-valued headers as csv-only.
*/
{{#nonPublicApi}}internal {{/nonPublicApi}}data class PartConfig<T>(
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}data class PartConfig<T>(
val headers: MutableMap<String, String> = mutableMapOf(),
val body: T? = null
)
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ package {{packageName}}.infrastructure
* NOTE: Headers is a Map<String,String> because rfc2616 defines
* multi-valued headers as csv-only.
*/
{{#nonPublicApi}}internal {{/nonPublicApi}}data class RequestConfig<T>(
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}data class RequestConfig<T>(
val method: RequestMethod,
val path: String,
val headers: MutableMap<String, String> = mutableMapOf(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ package {{packageName}}.infrastructure
/**
* Provides enumerated HTTP verbs
*/
{{#nonPublicApi}}internal {{/nonPublicApi}}enum class RequestMethod {
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}enum class RequestMethod {
GET, DELETE, HEAD, OPTIONS, PATCH, POST, PUT
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import kotlinx.serialization.descriptors.SerialDescriptor
import java.util.concurrent.atomic.AtomicBoolean

@Serializer(forClass = AtomicBoolean::class)
{{#nonPublicApi}}internal {{/nonPublicApi}}object AtomicBooleanAdapter : KSerializer<AtomicBoolean> {
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}object AtomicBooleanAdapter : KSerializer<AtomicBoolean> {
override fun serialize(encoder: Encoder, value: AtomicBoolean) {
encoder.encodeBoolean(value.get())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import kotlinx.serialization.descriptors.SerialDescriptor
import java.util.concurrent.atomic.AtomicInteger

@Serializer(forClass = AtomicInteger::class)
{{#nonPublicApi}}internal {{/nonPublicApi}}object AtomicIntegerAdapter : KSerializer<AtomicInteger> {
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}object AtomicIntegerAdapter : KSerializer<AtomicInteger> {
override fun serialize(encoder: Encoder, value: AtomicInteger) {
encoder.encodeInt(value.get())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import kotlinx.serialization.descriptors.SerialDescriptor
import java.util.concurrent.atomic.AtomicLong

@Serializer(forClass = AtomicLong::class)
{{#nonPublicApi}}internal {{/nonPublicApi}}object AtomicLongAdapter : KSerializer<AtomicLong> {
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}object AtomicLongAdapter : KSerializer<AtomicLong> {
override fun serialize(encoder: Encoder, value: AtomicLong) {
encoder.encodeLong(value.get())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@ import java.math.BigDecimal

{{#kotlinx_serialization}}
@Serializer(forClass = BigDecimal::class)
{{#nonPublicApi}}internal {{/nonPublicApi}}object BigDecimalAdapter : KSerializer<BigDecimal> {
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}object BigDecimalAdapter : KSerializer<BigDecimal> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("BigDecimal", PrimitiveKind.STRING)
override fun deserialize(decoder: Decoder): BigDecimal = BigDecimal(decoder.decodeString())
override fun serialize(encoder: Encoder, value: BigDecimal) = encoder.encodeString(value.toPlainString())
}
{{/kotlinx_serialization}}
{{#moshi}}
{{#nonPublicApi}}internal {{/nonPublicApi}}class BigDecimalAdapter {
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}class BigDecimalAdapter {
@ToJson
fun toJson(value: BigDecimal): String {
{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}fun toJson(value: BigDecimal): String {
return value.toPlainString()
}

@FromJson
fun fromJson(value: String): BigDecimal {
{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}fun fromJson(value: String): BigDecimal {
return BigDecimal(value)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import java.math.BigInteger

{{#kotlinx_serialization}}
@Serializer(forClass = BigInteger::class)
{{#nonPublicApi}}internal {{/nonPublicApi}}object BigIntegerAdapter : KSerializer<BigInteger> {
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}object BigIntegerAdapter : KSerializer<BigInteger> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("BigInteger", PrimitiveKind.STRING)
override fun deserialize(decoder: Decoder): BigInteger {
return BigInteger(decoder.decodeString())
Expand All @@ -29,14 +29,14 @@ import java.math.BigInteger
}
{{/kotlinx_serialization}}
{{#moshi}}
{{#nonPublicApi}}internal {{/nonPublicApi}}class BigIntegerAdapter {
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}class BigIntegerAdapter {
@ToJson
fun toJson(value: BigInteger): String {
{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}fun toJson(value: BigInteger): String {
return value.toString()
}

@FromJson
fun fromJson(value: String): BigInteger {
{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}fun fromJson(value: String): BigInteger {
return BigInteger(value)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ import java.io.IOException
{{/gson}}

{{#moshi}}
{{#nonPublicApi}}internal {{/nonPublicApi}}class ByteArrayAdapter {
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}class ByteArrayAdapter {
@ToJson
fun toJson(data: ByteArray): String = String(data)
{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}fun toJson(data: ByteArray): String = String(data)

@FromJson
fun fromJson(data: String): ByteArray = data.toByteArray()
{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}fun fromJson(data: String): ByteArray = data.toByteArray()
}
{{/moshi}}
{{#gson}}
{{#nonPublicApi}}internal {{/nonPublicApi}}class ByteArrayAdapter : TypeAdapter<ByteArray>() {
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}class ByteArrayAdapter : TypeAdapter<ByteArray>() {
@Throws(IOException::class)
override fun write(out: JsonWriter?, value: ByteArray?) {
if (value == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,21 @@ import java.io.IOException
import kotlinx.datetime.Instant

{{#moshi}}
{{#nonPublicApi}}internal {{/nonPublicApi}}class InstantAdapter {
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}class InstantAdapter {
@ToJson
fun toJson(value: Instant): String {
{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}fun toJson(value: Instant): String {
return value.toString()
}

@FromJson
fun fromJson(value: String): Instant {
{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}fun fromJson(value: String): Instant {
return Instant.parse(value)
}

}
{{/moshi}}
{{#gson}}
{{#nonPublicApi}}internal {{/nonPublicApi}}class InstantAdapter : TypeAdapter<Instant>() {
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}class InstantAdapter : TypeAdapter<Instant>() {
@Throws(IOException::class)
override fun write(out: JsonWriter?, value: Instant?) {
if (value == null) {
Expand Down
Loading