From 4cc508a3d337e955d35ed44f9b45f8c1b3e2016f Mon Sep 17 00:00:00 2001 From: Piotr Krzeminski Date: Tue, 22 Jun 2021 12:36:38 +0200 Subject: [PATCH 1/2] [#9805][Kotlin][multiplatform] Update Kotlin to 1.5.10 with related libraries The immediate goal of this commit is update the mentioned template to work with Kotlin 1.5.x. Currently when consuming the genrated module using Kotlin 1.3.50 from a Kotlin 1.5.x module with Ktor, starting the Ktor server fails in runtime. --- .../kotlin-client/data_class.mustache | 6 ++- .../kotlin-client/enum_class.mustache | 1 - .../infrastructure/RequestConfig.kt.mustache | 11 +++++ .../libraries/multiplatform/api.mustache | 41 +++++------------ .../multiplatform/build.gradle.mustache | 30 +++++++------ .../infrastructure/ApiClient.kt.mustache | 45 +++---------------- .../Base64ByteArray.kt.mustache | 7 ++- .../infrastructure/Bytes.kt.mustache | 4 +- .../infrastructure/HttpResponse.kt.mustache | 16 +++---- .../infrastructure/OctetByteArray.kt.mustache | 7 ++- .../serial_wrapper_request_list.mustache | 4 +- .../serial_wrapper_request_map.mustache | 4 +- .../serial_wrapper_response_list.mustache | 4 +- .../serial_wrapper_response_map.mustache | 4 +- 14 files changed, 75 insertions(+), 109 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/data_class.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/data_class.mustache index f840db6e394e..f42011ded091 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/data_class.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/data_class.mustache @@ -29,7 +29,6 @@ import kotlinx.parcelize.Parcelize {{/multiplatform}} {{#multiplatform}} import kotlinx.serialization.* -import kotlinx.serialization.internal.CommonEnumSerializer {{/multiplatform}} {{#serializableModel}} import java.io.Serializable @@ -72,6 +71,9 @@ import java.io.Serializable {{#kotlinx_serialization}} {{#serializableModel}}@KSerializable{{/serializableModel}}{{^serializableModel}}@Serializable{{/serializableModel}} {{/kotlinx_serialization}} + {{#multiplatform}} + @Serializable + {{/multiplatform}} {{#nonPublicApi}}internal {{/nonPublicApi}}enum class {{{nameInCamelCase}}}(val value: {{^isContainer}}{{dataType}}{{/isContainer}}{{#isContainer}}kotlin.String{{/isContainer}}) { {{#allowableValues}} {{#enumVars}} @@ -90,7 +92,7 @@ import java.io.Serializable {{/kotlinx_serialization}} {{/multiplatform}} {{#multiplatform}} - {{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}} + @SerialName(value = {{^isString}}"{{/isString}}{{{value}}}{{^isString}}"{{/isString}}) {{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}} {{/multiplatform}} {{/enumVars}} {{/allowableValues}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/enum_class.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/enum_class.mustache index 2071a6b537a2..609146654bb0 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/enum_class.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/enum_class.mustache @@ -15,7 +15,6 @@ import kotlinx.serialization.Serializable {{/multiplatform}} {{#multiplatform}} import kotlinx.serialization.* -import kotlinx.serialization.internal.CommonEnumSerializer {{/multiplatform}} /** diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/infrastructure/RequestConfig.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/infrastructure/RequestConfig.kt.mustache index ef1b0517e78d..2a8822808863 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/infrastructure/RequestConfig.kt.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/infrastructure/RequestConfig.kt.mustache @@ -8,10 +8,21 @@ package {{packageName}}.infrastructure * NOTE: Headers is a Map because rfc2616 defines * multi-valued headers as csv-only. */ +{{^multiplatform}} {{#nonPublicApi}}internal {{/nonPublicApi}}data class RequestConfig( +{{/multiplatform}} +{{#multiplatform}} +{{! Migrating the 'multiplatform' template to RequestConfig is considered a separate piece of effort. }} +{{#nonPublicApi}}internal {{/nonPublicApi}}data class RequestConfig( +{{/multiplatform}} val method: RequestMethod, val path: String, val headers: MutableMap = mutableMapOf(), val query: MutableMap> = mutableMapOf(), + {{^multiplatform}} val body: T? = null + {{/multiplatform}} + {{#multiplatform}} + val body: kotlin.Any? = null + {{/multiplatform}} ) \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/api.mustache index e51da4590b88..ca24834f18ba 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/api.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/api.mustache @@ -6,29 +6,26 @@ package {{apiPackage}} import {{packageName}}.infrastructure.* import io.ktor.client.request.forms.formData -import kotlinx.serialization.UnstableDefault import io.ktor.client.engine.HttpClientEngine import io.ktor.client.features.json.serializer.KotlinxSerializer -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonConfiguration import io.ktor.http.ParametersBuilder import kotlinx.serialization.* -import kotlinx.serialization.internal.StringDescriptor +import kotlinx.serialization.builtins.* +import kotlinx.serialization.json.Json +import kotlinx.serialization.builtins.ListSerializer +import kotlinx.serialization.builtins.MapSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder {{#operations}} -{{#nonPublicApi}}internal {{/nonPublicApi}}class {{classname}} @UseExperimental(UnstableDefault::class) constructor( +{{#nonPublicApi}}internal {{/nonPublicApi}}class {{classname}} constructor( baseUrl: kotlin.String = "{{{basePath}}}", httpClientEngine: HttpClientEngine? = null, - serializer: KotlinxSerializer + serializer: KotlinxSerializer = KotlinxSerializer(Json { ignoreUnknownKeys = true }), ) : ApiClient(baseUrl, httpClientEngine, serializer) { - @UseExperimental(UnstableDefault::class) - constructor( - baseUrl: kotlin.String = "{{{basePath}}}", - httpClientEngine: HttpClientEngine? = null, - jsonConfiguration: JsonConfiguration = JsonConfiguration.Default - ) : this(baseUrl, httpClientEngine, KotlinxSerializer(Json(jsonConfiguration))) - {{#operation}} /** * {{summary}} @@ -103,23 +100,5 @@ import kotlinx.serialization.internal.StringDescriptor {{/isMap}} {{/operation}} - - {{#nonPublicApi}}internal {{/nonPublicApi}}companion object { - internal fun setMappers(serializer: KotlinxSerializer) { - {{#operation}} - {{#hasBodyParam}} - {{#bodyParam}} - {{#isArray}}serializer.setMapper({{operationIdCamelCase}}Request::class, {{operationIdCamelCase}}Request.serializer()){{/isArray}}{{#isMap}}serializer.setMapper({{operationIdCamelCase}}Request::class, {{operationIdCamelCase}}Request.serializer()){{/isMap}} - {{/bodyParam}} - {{/hasBodyParam}} - {{#isArray}} - serializer.setMapper({{operationIdCamelCase}}Response::class, {{operationIdCamelCase}}Response.serializer()) - {{/isArray}} - {{#isMap}} - serializer.setMapper({{operationIdCamelCase}}Response::class, {{operationIdCamelCase}}Response.serializer()) - {{/isMap}} - {{/operation}} - } - } } {{/operations}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/build.gradle.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/build.gradle.mustache index dfc6736dc6d5..02577c0e2c2a 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/build.gradle.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/build.gradle.mustache @@ -5,11 +5,12 @@ group '{{groupId}}' version '{{artifactVersion}}' ext { - kotlin_version = '1.3.50' - kotlinx_version = '1.1.0' - coroutines_version = '1.3.1' - serialization_version = '0.12.0' - ktor_version = '1.2.4' + // Recommended library versions for the used version of Kotlin were taken from + // https://kotlinlang.org/docs/releases.html#release-details + kotlin_version = '1.5.10' + coroutines_version = '1.5.0' + serialization_version = '1.2.1' + ktor_version = '1.5.4' } buildscript { @@ -17,8 +18,8 @@ buildscript { jcenter() } dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.50" // $kotlin_version - classpath "org.jetbrains.kotlin:kotlin-serialization:1.3.50" // $kotlin_version + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.10" // $kotlin_version + classpath "org.jetbrains.kotlin:kotlin-serialization:1.5.10" // $kotlin_version } } @@ -28,16 +29,16 @@ repositories { kotlin { jvm() - iosArm64() { binaries { framework { freeCompilerArgs.add("-Xobjc-generics") } } } - iosX64() { binaries { framework { freeCompilerArgs.add("-Xobjc-generics") } } } + iosArm64() { binaries { framework { freeCompilerArgs += "-Xobjc-generics" } } } + iosX64() { binaries { framework { freeCompilerArgs += "-Xobjc-generics" } } } js() sourceSets { commonMain { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$coroutines_version" - implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serialization_version" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" + implementation "org.jetbrains.kotlinx:kotlinx-serialization-core:$serialization_version" api "io.ktor:ktor-client-core:$ktor_version" api "io.ktor:ktor-client-json:$ktor_version" api "io.ktor:ktor-client-serialization:$ktor_version" @@ -57,7 +58,8 @@ kotlin { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" - implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serialization_version" + implementation "org.jetbrains.kotlinx:kotlinx-serialization-core:$serialization_version" + implementation "io.ktor:ktor-client-cio-jvm:$ktor_version" api "io.ktor:ktor-client-core-jvm:$ktor_version" api "io.ktor:ktor-client-json-jvm:$ktor_version" api "io.ktor:ktor-client-serialization-jvm:$ktor_version" @@ -77,7 +79,7 @@ kotlin { dependsOn commonMain dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$coroutines_version" - implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:$serialization_version" + implementation "org.jetbrains.kotlinx:kotlinx-serialization-core-native:$serialization_version" api "io.ktor:ktor-client-ios:$ktor_version" } } @@ -116,7 +118,7 @@ kotlin { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-js:$coroutines_version" - implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:$serialization_version" + implementation "org.jetbrains.kotlinx:kotlinx-serialization-core-js:$serialization_version" api "io.ktor:ktor-client-js:$ktor_version" api "io.ktor:ktor-client-json-js:$ktor_version" api "io.ktor:ktor-client-serialization-js:$ktor_version" diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/infrastructure/ApiClient.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/infrastructure/ApiClient.kt.mustache index b1cf9583bdbf..2883a5e69721 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/infrastructure/ApiClient.kt.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/infrastructure/ApiClient.kt.mustache @@ -7,19 +7,16 @@ import io.ktor.client.engine.HttpClientEngine import io.ktor.client.features.json.JsonFeature import io.ktor.client.features.json.JsonSerializer import io.ktor.client.features.json.serializer.KotlinxSerializer -import io.ktor.client.request.accept +import io.ktor.client.request.request import io.ktor.client.request.forms.FormDataContent import io.ktor.client.request.forms.MultiPartFormDataContent import io.ktor.client.request.header import io.ktor.client.request.parameter -import io.ktor.client.response.HttpResponse +import io.ktor.client.statement.HttpResponse import io.ktor.client.utils.EmptyContent import io.ktor.http.* import io.ktor.http.content.OutgoingContent import io.ktor.http.content.PartData -import kotlinx.serialization.UnstableDefault -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonConfiguration import {{apiPackage}}.* import {{modelPackage}}.* @@ -28,18 +25,7 @@ import {{packageName}}.auth.* {{#nonPublicApi}}internal {{/nonPublicApi}}open class ApiClient( private val baseUrl: String, httpClientEngine: HttpClientEngine?, - serializer: KotlinxSerializer) { - - @UseExperimental(UnstableDefault::class) - constructor( - baseUrl: String, - httpClientEngine: HttpClientEngine?, - jsonConfiguration: JsonConfiguration) : - this(baseUrl, httpClientEngine, KotlinxSerializer(Json(jsonConfiguration))) - - private val serializer: JsonSerializer by lazy { - serializer.apply { setMappers(this) }.ignoreOutgoingContent() - } + private val serializer: KotlinxSerializer) { private val client: HttpClient by lazy { val jsonConfig: JsonFeature.Config.() -> Unit = { this.serializer = this@ApiClient.serializer } @@ -61,15 +47,6 @@ import {{packageName}}.auth.* {{#nonPublicApi}}internal {{/nonPublicApi}}companion object { protected val UNSAFE_HEADERS = listOf(HttpHeaders.ContentType) - - private fun setMappers(serializer: KotlinxSerializer) { - {{#apiInfo}}{{#apis}} - {{classname}}.setMappers(serializer) - {{/apis}}{{/apiInfo}} - {{#models}} - {{#model}}{{^isAlias}}serializer.setMapper({{modelPackage}}.{{classname}}::class, {{modelPackage}}.{{classname}}.{{#isEnum}}Serializer{{/isEnum}}{{^isEnum}}serializer(){{/isEnum}}){{/isAlias}}{{/model}} - {{/models}} - } } /** @@ -155,11 +132,11 @@ import {{packageName}}.auth.* else request(requestConfig, authNames = authNames) } - protected suspend inline fun request(requestConfig: RequestConfig, body: OutgoingContent = EmptyContent, authNames: kotlin.collections.List): HttpResponse { + protected suspend fun request(requestConfig: RequestConfig, body: OutgoingContent = EmptyContent, authNames: kotlin.collections.List): HttpResponse { requestConfig.updateForAuth(authNames) val headers = requestConfig.headers - return client.call { + return client.request { this.url { this.takeFrom(URLBuilder(baseUrl)) appendPath(requestConfig.path.trimStart('/').split('/')) @@ -174,7 +151,7 @@ import {{packageName}}.auth.* if (requestConfig.method in listOf(RequestMethod.PUT, RequestMethod.POST, RequestMethod.PATCH)) this.body = body - }.response + } } private fun RequestConfig.updateForAuth(authNames: kotlin.collections.List) { @@ -199,13 +176,3 @@ import {{packageName}}.auth.* RequestMethod.OPTIONS -> HttpMethod.Options } } - -// https://github.com/ktorio/ktor/issues/851 -private fun JsonSerializer.ignoreOutgoingContent() = IgnoreOutgoingContentJsonSerializer(this) - -private class IgnoreOutgoingContentJsonSerializer(private val delegate: JsonSerializer) : JsonSerializer by delegate { - override fun write(data: Any): OutgoingContent { - if (data is OutgoingContent) return data - return delegate.write(data) - } -} diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/infrastructure/Base64ByteArray.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/infrastructure/Base64ByteArray.kt.mustache index 168cfc993c3b..b8b05e3f010f 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/infrastructure/Base64ByteArray.kt.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/infrastructure/Base64ByteArray.kt.mustache @@ -1,13 +1,16 @@ package {{packageName}}.infrastructure import kotlinx.serialization.* -import kotlinx.serialization.internal.StringDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder @Serializable class Base64ByteArray(val value: ByteArray) { @Serializer(Base64ByteArray::class) companion object : KSerializer { - override val descriptor = StringDescriptor.withName("Base64ByteArray") + override val descriptor = PrimitiveSerialDescriptor("Base64ByteArray", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, obj: Base64ByteArray) = encoder.encodeString(obj.value.encodeBase64()) override fun deserialize(decoder: Decoder) = Base64ByteArray(decoder.decodeString().decodeBase64Bytes()) } diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/infrastructure/Bytes.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/infrastructure/Bytes.kt.mustache index b85013e647b2..e882220ade6d 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/infrastructure/Bytes.kt.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/infrastructure/Bytes.kt.mustache @@ -1,6 +1,6 @@ package {{packageName}}.infrastructure -import kotlinx.io.core.* +import io.ktor.utils.io.core.* import kotlin.experimental.and private val digits = "0123456789abcdef".toCharArray() @@ -32,7 +32,7 @@ internal fun hex(bytes: ByteArray): String { result[resultIndex++] = digits[b and 0x0f] } - return String(result) + return result.concatToString() } /** diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/infrastructure/HttpResponse.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/infrastructure/HttpResponse.kt.mustache index 87f27a5cf56f..12d265674611 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/infrastructure/HttpResponse.kt.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/infrastructure/HttpResponse.kt.mustache @@ -5,7 +5,7 @@ import io.ktor.client.call.typeInfo import io.ktor.http.Headers import io.ktor.http.isSuccess -{{#nonPublicApi}}internal {{/nonPublicApi}}open class HttpResponse(val response: io.ktor.client.response.HttpResponse, val provider: BodyProvider) { +{{#nonPublicApi}}internal {{/nonPublicApi}}open class HttpResponse(val response: io.ktor.client.statement.HttpResponse, val provider: BodyProvider) { val status: Int = response.status.value val success: Boolean = response.status.isSuccess() val headers: Map> = response.headers.mapEntries() @@ -22,29 +22,29 @@ import io.ktor.http.isSuccess } {{#nonPublicApi}}internal {{/nonPublicApi}}interface BodyProvider { - suspend fun body(response: io.ktor.client.response.HttpResponse): T - suspend fun typedBody(response: io.ktor.client.response.HttpResponse, type: TypeInfo): V + suspend fun body(response: io.ktor.client.statement.HttpResponse): T + suspend fun typedBody(response: io.ktor.client.statement.HttpResponse, type: TypeInfo): V } {{#nonPublicApi}}internal {{/nonPublicApi}}class TypedBodyProvider(private val type: TypeInfo) : BodyProvider { @Suppress("UNCHECKED_CAST") - override suspend fun body(response: io.ktor.client.response.HttpResponse): T = + override suspend fun body(response: io.ktor.client.statement.HttpResponse): T = response.call.receive(type) as T @Suppress("UNCHECKED_CAST") - override suspend fun typedBody(response: io.ktor.client.response.HttpResponse, type: TypeInfo): V = + override suspend fun typedBody(response: io.ktor.client.statement.HttpResponse, type: TypeInfo): V = response.call.receive(type) as V } {{#nonPublicApi}}internal {{/nonPublicApi}}class MappedBodyProvider(private val provider: BodyProvider, private val block: S.() -> T) : BodyProvider { - override suspend fun body(response: io.ktor.client.response.HttpResponse): T = + override suspend fun body(response: io.ktor.client.statement.HttpResponse): T = block(provider.body(response)) - override suspend fun typedBody(response: io.ktor.client.response.HttpResponse, type: TypeInfo): V = + override suspend fun typedBody(response: io.ktor.client.statement.HttpResponse, type: TypeInfo): V = provider.typedBody(response, type) } -{{#nonPublicApi}}internal {{/nonPublicApi}}inline fun io.ktor.client.response.HttpResponse.wrap(): HttpResponse = +{{#nonPublicApi}}internal {{/nonPublicApi}}inline fun io.ktor.client.statement.HttpResponse.wrap(): HttpResponse = HttpResponse(this, TypedBodyProvider(typeInfo())) {{#nonPublicApi}}internal {{/nonPublicApi}}fun HttpResponse.map(block: T.() -> V): HttpResponse = diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/infrastructure/OctetByteArray.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/infrastructure/OctetByteArray.kt.mustache index c23ac3ec0001..bae36b702707 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/infrastructure/OctetByteArray.kt.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/infrastructure/OctetByteArray.kt.mustache @@ -1,13 +1,16 @@ package {{packageName}}.infrastructure import kotlinx.serialization.* -import kotlinx.serialization.internal.StringDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder @Serializable class OctetByteArray(val value: ByteArray) { @Serializer(OctetByteArray::class) companion object : KSerializer { - override val descriptor = StringDescriptor.withName("OctetByteArray") + override val descriptor = PrimitiveSerialDescriptor("OctetByteArray", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, obj: OctetByteArray) = encoder.encodeString(hex(obj.value)) override fun deserialize(decoder: Decoder) = OctetByteArray(hex(decoder.decodeString())) } diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/serial_wrapper_request_list.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/serial_wrapper_request_list.mustache index a44a242cbd2d..83cbd0d634ec 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/serial_wrapper_request_list.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/serial_wrapper_request_list.mustache @@ -2,8 +2,8 @@ private class {{operationIdCamelCase}}Request(val value: List<{{#bodyParam}}{{baseType}}{{/bodyParam}}>) { @Serializer({{operationIdCamelCase}}Request::class) {{#nonPublicApi}}internal {{/nonPublicApi}}companion object : KSerializer<{{operationIdCamelCase}}Request> { - private val serializer: KSerializer> = {{#bodyParam}}{{baseType}}{{/bodyParam}}.serializer().list - override val descriptor = StringDescriptor.withName("{{operationIdCamelCase}}Request") + private val serializer: KSerializer> = ListSerializer({{#bodyParam}}{{baseType}}{{/bodyParam}}.serializer()) + override val descriptor = PrimitiveSerialDescriptor("{{operationIdCamelCase}}Request", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, obj: {{operationIdCamelCase}}Request) = serializer.serialize(encoder, obj.value) override fun deserialize(decoder: Decoder) = {{operationIdCamelCase}}Request(serializer.deserialize(decoder)) } diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/serial_wrapper_request_map.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/serial_wrapper_request_map.mustache index 5dc6864aae82..167e75563d45 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/serial_wrapper_request_map.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/serial_wrapper_request_map.mustache @@ -2,8 +2,8 @@ private class {{operationIdCamelCase}}Request(val value: Map) { @Serializer({{operationIdCamelCase}}Request::class) {{#nonPublicApi}}internal {{/nonPublicApi}}companion object : KSerializer<{{operationIdCamelCase}}Request> { - private val serializer: KSerializer> = (kotlin.String.serializer() to {{#bodyParam}}{{baseType}}{{/bodyParam}}.serializer()).map - override val descriptor = StringDescriptor.withName("{{operationIdCamelCase}}Request") + private val serializer: KSerializer> = MapSerializer(kotlin.String.serializer(), {{#bodyParam}}{{baseType}}{{/bodyParam}}.serializer()) + override val descriptor = PrimitiveSerialDescriptor("{{operationIdCamelCase}}Request", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, obj: {{operationIdCamelCase}}Request) = serializer.serialize(encoder, obj.value) override fun deserialize(decoder: Decoder) = {{operationIdCamelCase}}Request(serializer.deserialize(decoder)) } diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/serial_wrapper_response_list.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/serial_wrapper_response_list.mustache index a4e70a219ca4..74575e069a4a 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/serial_wrapper_response_list.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/serial_wrapper_response_list.mustache @@ -2,8 +2,8 @@ private class {{operationIdCamelCase}}Response(val value: List<{{returnBaseType}}>) { @Serializer({{operationIdCamelCase}}Response::class) {{#nonPublicApi}}internal {{/nonPublicApi}}companion object : KSerializer<{{operationIdCamelCase}}Response> { - private val serializer: KSerializer> = {{returnBaseType}}.serializer().list - override val descriptor = StringDescriptor.withName("{{operationIdCamelCase}}Response") + private val serializer: KSerializer> = ListSerializer({{returnBaseType}}.serializer()) + override val descriptor = PrimitiveSerialDescriptor("{{operationIdCamelCase}}Response", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, obj: {{operationIdCamelCase}}Response) = serializer.serialize(encoder, obj.value) override fun deserialize(decoder: Decoder) = {{operationIdCamelCase}}Response(serializer.deserialize(decoder)) } diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/serial_wrapper_response_map.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/serial_wrapper_response_map.mustache index 8253dc1f1a1c..a5c9a9605609 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/serial_wrapper_response_map.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/multiplatform/serial_wrapper_response_map.mustache @@ -2,8 +2,8 @@ private class {{operationIdCamelCase}}Response(val value: Map) { @Serializer({{operationIdCamelCase}}Response::class) {{#nonPublicApi}}internal {{/nonPublicApi}}companion object : KSerializer<{{operationIdCamelCase}}Response> { - private val serializer: KSerializer> = (kotlin.String.serializer() to {{returnBaseType}}.serializer()).map - override val descriptor = StringDescriptor.withName("{{operationIdCamelCase}}Response") + private val serializer: KSerializer> = MapSerializer(kotlin.String.serializer(), {{returnBaseType}}.serializer()) + override val descriptor = PrimitiveSerialDescriptor("{{operationIdCamelCase}}Response", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, obj: {{operationIdCamelCase}}Response) = serializer.serialize(encoder, obj.value) override fun deserialize(decoder: Decoder) = {{operationIdCamelCase}}Response(serializer.deserialize(decoder)) } From d38e137abbc1e3d60937ca7045251408438ba89e Mon Sep 17 00:00:00 2001 From: Piotr Krzeminski Date: Tue, 22 Jun 2021 14:06:12 +0200 Subject: [PATCH 2/2] [#9805][Kotlin][multiplatform] Update sample project --- .../kotlin-multiplatform/build.gradle | 30 ++++++----- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../org/openapitools/client/apis/PetApi.kt | 42 ++++++--------- .../org/openapitools/client/apis/StoreApi.kt | 36 +++++-------- .../org/openapitools/client/apis/UserApi.kt | 42 ++++++--------- .../client/infrastructure/ApiClient.kt | 52 +++---------------- .../client/infrastructure/Base64ByteArray.kt | 7 ++- .../client/infrastructure/Bytes.kt | 4 +- .../client/infrastructure/HttpResponse.kt | 16 +++--- .../client/infrastructure/OctetByteArray.kt | 7 ++- .../client/infrastructure/RequestConfig.kt | 4 +- .../openapitools/client/models/ApiResponse.kt | 1 - .../openapitools/client/models/Category.kt | 1 - .../org/openapitools/client/models/Order.kt | 8 +-- .../org/openapitools/client/models/Pet.kt | 8 +-- .../org/openapitools/client/models/Tag.kt | 1 - .../org/openapitools/client/models/User.kt | 1 - 17 files changed, 96 insertions(+), 166 deletions(-) diff --git a/samples/client/petstore/kotlin-multiplatform/build.gradle b/samples/client/petstore/kotlin-multiplatform/build.gradle index 47045bb577e1..35a6a931322b 100644 --- a/samples/client/petstore/kotlin-multiplatform/build.gradle +++ b/samples/client/petstore/kotlin-multiplatform/build.gradle @@ -5,11 +5,12 @@ group 'org.openapitools' version '1.0.0' ext { - kotlin_version = '1.3.50' - kotlinx_version = '1.1.0' - coroutines_version = '1.3.1' - serialization_version = '0.12.0' - ktor_version = '1.2.4' + // Recommended library versions for the used version of Kotlin were taken from + // https://kotlinlang.org/docs/releases.html#release-details + kotlin_version = '1.5.10' + coroutines_version = '1.5.0' + serialization_version = '1.2.1' + ktor_version = '1.5.4' } buildscript { @@ -17,8 +18,8 @@ buildscript { jcenter() } dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.50" // $kotlin_version - classpath "org.jetbrains.kotlin:kotlin-serialization:1.3.50" // $kotlin_version + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.10" // $kotlin_version + classpath "org.jetbrains.kotlin:kotlin-serialization:1.5.10" // $kotlin_version } } @@ -28,16 +29,16 @@ repositories { kotlin { jvm() - iosArm64() { binaries { framework { freeCompilerArgs.add("-Xobjc-generics") } } } - iosX64() { binaries { framework { freeCompilerArgs.add("-Xobjc-generics") } } } + iosArm64() { binaries { framework { freeCompilerArgs += "-Xobjc-generics" } } } + iosX64() { binaries { framework { freeCompilerArgs += "-Xobjc-generics" } } } js() sourceSets { commonMain { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$coroutines_version" - implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serialization_version" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" + implementation "org.jetbrains.kotlinx:kotlinx-serialization-core:$serialization_version" api "io.ktor:ktor-client-core:$ktor_version" api "io.ktor:ktor-client-json:$ktor_version" api "io.ktor:ktor-client-serialization:$ktor_version" @@ -57,7 +58,8 @@ kotlin { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" - implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serialization_version" + implementation "org.jetbrains.kotlinx:kotlinx-serialization-core:$serialization_version" + implementation "io.ktor:ktor-client-cio-jvm:$ktor_version" api "io.ktor:ktor-client-core-jvm:$ktor_version" api "io.ktor:ktor-client-json-jvm:$ktor_version" api "io.ktor:ktor-client-serialization-jvm:$ktor_version" @@ -77,7 +79,7 @@ kotlin { dependsOn commonMain dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$coroutines_version" - implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:$serialization_version" + implementation "org.jetbrains.kotlinx:kotlinx-serialization-core-native:$serialization_version" api "io.ktor:ktor-client-ios:$ktor_version" } } @@ -116,7 +118,7 @@ kotlin { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-js:$coroutines_version" - implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:$serialization_version" + implementation "org.jetbrains.kotlinx:kotlinx-serialization-core-js:$serialization_version" api "io.ktor:ktor-client-js:$ktor_version" api "io.ktor:ktor-client-json-js:$ktor_version" api "io.ktor:ktor-client-serialization-js:$ktor_version" diff --git a/samples/client/petstore/kotlin-multiplatform/gradle/wrapper/gradle-wrapper.properties b/samples/client/petstore/kotlin-multiplatform/gradle/wrapper/gradle-wrapper.properties index 6ce793f21e85..ba94df8451ff 100644 --- a/samples/client/petstore/kotlin-multiplatform/gradle/wrapper/gradle-wrapper.properties +++ b/samples/client/petstore/kotlin-multiplatform/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/apis/PetApi.kt b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/apis/PetApi.kt index e164a6cf4d06..89a02587b706 100644 --- a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/apis/PetApi.kt +++ b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/apis/PetApi.kt @@ -16,28 +16,25 @@ import org.openapitools.client.models.Pet import org.openapitools.client.infrastructure.* import io.ktor.client.request.forms.formData -import kotlinx.serialization.UnstableDefault import io.ktor.client.engine.HttpClientEngine import io.ktor.client.features.json.serializer.KotlinxSerializer -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonConfiguration import io.ktor.http.ParametersBuilder import kotlinx.serialization.* -import kotlinx.serialization.internal.StringDescriptor - -class PetApi @UseExperimental(UnstableDefault::class) constructor( +import kotlinx.serialization.builtins.* +import kotlinx.serialization.json.Json +import kotlinx.serialization.builtins.ListSerializer +import kotlinx.serialization.builtins.MapSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +class PetApi constructor( baseUrl: kotlin.String = "http://petstore.swagger.io/v2", httpClientEngine: HttpClientEngine? = null, - serializer: KotlinxSerializer + serializer: KotlinxSerializer = KotlinxSerializer(Json { ignoreUnknownKeys = true }), ) : ApiClient(baseUrl, httpClientEngine, serializer) { - @UseExperimental(UnstableDefault::class) - constructor( - baseUrl: kotlin.String = "http://petstore.swagger.io/v2", - httpClientEngine: HttpClientEngine? = null, - jsonConfiguration: JsonConfiguration = JsonConfiguration.Default - ) : this(baseUrl, httpClientEngine, KotlinxSerializer(Json(jsonConfiguration))) - /** * Add a new pet to the store * @@ -141,8 +138,8 @@ class PetApi @UseExperimental(UnstableDefault::class) constructor( private class FindPetsByStatusResponse(val value: List) { @Serializer(FindPetsByStatusResponse::class) companion object : KSerializer { - private val serializer: KSerializer> = Pet.serializer().list - override val descriptor = StringDescriptor.withName("FindPetsByStatusResponse") + private val serializer: KSerializer> = ListSerializer(Pet.serializer()) + override val descriptor = PrimitiveSerialDescriptor("FindPetsByStatusResponse", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, obj: FindPetsByStatusResponse) = serializer.serialize(encoder, obj.value) override fun deserialize(decoder: Decoder) = FindPetsByStatusResponse(serializer.deserialize(decoder)) } @@ -185,8 +182,8 @@ class PetApi @UseExperimental(UnstableDefault::class) constructor( private class FindPetsByTagsResponse(val value: List) { @Serializer(FindPetsByTagsResponse::class) companion object : KSerializer { - private val serializer: KSerializer> = Pet.serializer().list - override val descriptor = StringDescriptor.withName("FindPetsByTagsResponse") + private val serializer: KSerializer> = ListSerializer(Pet.serializer()) + override val descriptor = PrimitiveSerialDescriptor("FindPetsByTagsResponse", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, obj: FindPetsByTagsResponse) = serializer.serialize(encoder, obj.value) override fun deserialize(decoder: Decoder) = FindPetsByTagsResponse(serializer.deserialize(decoder)) } @@ -332,13 +329,4 @@ class PetApi @UseExperimental(UnstableDefault::class) constructor( } - - companion object { - internal fun setMappers(serializer: KotlinxSerializer) { - - serializer.setMapper(FindPetsByStatusResponse::class, FindPetsByStatusResponse.serializer()) - serializer.setMapper(FindPetsByTagsResponse::class, FindPetsByTagsResponse.serializer()) - - } - } } diff --git a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/apis/StoreApi.kt b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/apis/StoreApi.kt index 8ca30e8ca3a3..7ef2a32138a1 100644 --- a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/apis/StoreApi.kt +++ b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/apis/StoreApi.kt @@ -15,28 +15,25 @@ import org.openapitools.client.models.Order import org.openapitools.client.infrastructure.* import io.ktor.client.request.forms.formData -import kotlinx.serialization.UnstableDefault import io.ktor.client.engine.HttpClientEngine import io.ktor.client.features.json.serializer.KotlinxSerializer -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonConfiguration import io.ktor.http.ParametersBuilder import kotlinx.serialization.* -import kotlinx.serialization.internal.StringDescriptor - -class StoreApi @UseExperimental(UnstableDefault::class) constructor( +import kotlinx.serialization.builtins.* +import kotlinx.serialization.json.Json +import kotlinx.serialization.builtins.ListSerializer +import kotlinx.serialization.builtins.MapSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +class StoreApi constructor( baseUrl: kotlin.String = "http://petstore.swagger.io/v2", httpClientEngine: HttpClientEngine? = null, - serializer: KotlinxSerializer + serializer: KotlinxSerializer = KotlinxSerializer(Json { ignoreUnknownKeys = true }), ) : ApiClient(baseUrl, httpClientEngine, serializer) { - @UseExperimental(UnstableDefault::class) - constructor( - baseUrl: kotlin.String = "http://petstore.swagger.io/v2", - httpClientEngine: HttpClientEngine? = null, - jsonConfiguration: JsonConfiguration = JsonConfiguration.Default - ) : this(baseUrl, httpClientEngine, KotlinxSerializer(Json(jsonConfiguration))) - /** * Delete purchase order by ID * For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors @@ -104,8 +101,8 @@ class StoreApi @UseExperimental(UnstableDefault::class) constructor( private class GetInventoryResponse(val value: Map) { @Serializer(GetInventoryResponse::class) companion object : KSerializer { - private val serializer: KSerializer> = (kotlin.String.serializer() to kotlin.Int.serializer()).map - override val descriptor = StringDescriptor.withName("GetInventoryResponse") + private val serializer: KSerializer> = MapSerializer(kotlin.String.serializer(), kotlin.Int.serializer()) + override val descriptor = PrimitiveSerialDescriptor("GetInventoryResponse", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, obj: GetInventoryResponse) = serializer.serialize(encoder, obj.value) override fun deserialize(decoder: Decoder) = GetInventoryResponse(serializer.deserialize(decoder)) } @@ -177,11 +174,4 @@ class StoreApi @UseExperimental(UnstableDefault::class) constructor( - - companion object { - internal fun setMappers(serializer: KotlinxSerializer) { - serializer.setMapper(GetInventoryResponse::class, GetInventoryResponse.serializer()) - - } - } } diff --git a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/apis/UserApi.kt b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/apis/UserApi.kt index 88474dc9ef80..dbd63d96a30f 100644 --- a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/apis/UserApi.kt +++ b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/apis/UserApi.kt @@ -15,28 +15,25 @@ import org.openapitools.client.models.User import org.openapitools.client.infrastructure.* import io.ktor.client.request.forms.formData -import kotlinx.serialization.UnstableDefault import io.ktor.client.engine.HttpClientEngine import io.ktor.client.features.json.serializer.KotlinxSerializer -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonConfiguration import io.ktor.http.ParametersBuilder import kotlinx.serialization.* -import kotlinx.serialization.internal.StringDescriptor - -class UserApi @UseExperimental(UnstableDefault::class) constructor( +import kotlinx.serialization.builtins.* +import kotlinx.serialization.json.Json +import kotlinx.serialization.builtins.ListSerializer +import kotlinx.serialization.builtins.MapSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +class UserApi constructor( baseUrl: kotlin.String = "http://petstore.swagger.io/v2", httpClientEngine: HttpClientEngine? = null, - serializer: KotlinxSerializer + serializer: KotlinxSerializer = KotlinxSerializer(Json { ignoreUnknownKeys = true }), ) : ApiClient(baseUrl, httpClientEngine, serializer) { - @UseExperimental(UnstableDefault::class) - constructor( - baseUrl: kotlin.String = "http://petstore.swagger.io/v2", - httpClientEngine: HttpClientEngine? = null, - jsonConfiguration: JsonConfiguration = JsonConfiguration.Default - ) : this(baseUrl, httpClientEngine, KotlinxSerializer(Json(jsonConfiguration))) - /** * Create user * This can only be done by the logged in user. @@ -103,8 +100,8 @@ class UserApi @UseExperimental(UnstableDefault::class) constructor( private class CreateUsersWithArrayInputRequest(val value: List) { @Serializer(CreateUsersWithArrayInputRequest::class) companion object : KSerializer { - private val serializer: KSerializer> = User.serializer().list - override val descriptor = StringDescriptor.withName("CreateUsersWithArrayInputRequest") + private val serializer: KSerializer> = ListSerializer(User.serializer()) + override val descriptor = PrimitiveSerialDescriptor("CreateUsersWithArrayInputRequest", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, obj: CreateUsersWithArrayInputRequest) = serializer.serialize(encoder, obj.value) override fun deserialize(decoder: Decoder) = CreateUsersWithArrayInputRequest(serializer.deserialize(decoder)) } @@ -144,8 +141,8 @@ class UserApi @UseExperimental(UnstableDefault::class) constructor( private class CreateUsersWithListInputRequest(val value: List) { @Serializer(CreateUsersWithListInputRequest::class) companion object : KSerializer { - private val serializer: KSerializer> = User.serializer().list - override val descriptor = StringDescriptor.withName("CreateUsersWithListInputRequest") + private val serializer: KSerializer> = ListSerializer(User.serializer()) + override val descriptor = PrimitiveSerialDescriptor("CreateUsersWithListInputRequest", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, obj: CreateUsersWithListInputRequest) = serializer.serialize(encoder, obj.value) override fun deserialize(decoder: Decoder) = CreateUsersWithListInputRequest(serializer.deserialize(decoder)) } @@ -316,13 +313,4 @@ class UserApi @UseExperimental(UnstableDefault::class) constructor( - - companion object { - internal fun setMappers(serializer: KotlinxSerializer) { - - serializer.setMapper(CreateUsersWithArrayInputRequest::class, CreateUsersWithArrayInputRequest.serializer()) - serializer.setMapper(CreateUsersWithListInputRequest::class, CreateUsersWithListInputRequest.serializer()) - - } - } } diff --git a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index 42d2a68d5b44..1d5271b8e22d 100644 --- a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -7,19 +7,16 @@ import io.ktor.client.engine.HttpClientEngine import io.ktor.client.features.json.JsonFeature import io.ktor.client.features.json.JsonSerializer import io.ktor.client.features.json.serializer.KotlinxSerializer -import io.ktor.client.request.accept +import io.ktor.client.request.request import io.ktor.client.request.forms.FormDataContent import io.ktor.client.request.forms.MultiPartFormDataContent import io.ktor.client.request.header import io.ktor.client.request.parameter -import io.ktor.client.response.HttpResponse +import io.ktor.client.statement.HttpResponse import io.ktor.client.utils.EmptyContent import io.ktor.http.* import io.ktor.http.content.OutgoingContent import io.ktor.http.content.PartData -import kotlinx.serialization.UnstableDefault -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonConfiguration import org.openapitools.client.apis.* import org.openapitools.client.models.* @@ -28,18 +25,7 @@ import org.openapitools.client.auth.* open class ApiClient( private val baseUrl: String, httpClientEngine: HttpClientEngine?, - serializer: KotlinxSerializer) { - - @UseExperimental(UnstableDefault::class) - constructor( - baseUrl: String, - httpClientEngine: HttpClientEngine?, - jsonConfiguration: JsonConfiguration) : - this(baseUrl, httpClientEngine, KotlinxSerializer(Json(jsonConfiguration))) - - private val serializer: JsonSerializer by lazy { - serializer.apply { setMappers(this) }.ignoreOutgoingContent() - } + private val serializer: KotlinxSerializer) { private val client: HttpClient by lazy { val jsonConfig: JsonFeature.Config.() -> Unit = { this.serializer = this@ApiClient.serializer } @@ -54,22 +40,6 @@ open class ApiClient( companion object { protected val UNSAFE_HEADERS = listOf(HttpHeaders.ContentType) - - private fun setMappers(serializer: KotlinxSerializer) { - - PetApi.setMappers(serializer) - - StoreApi.setMappers(serializer) - - UserApi.setMappers(serializer) - - serializer.setMapper(org.openapitools.client.models.ApiResponse::class, org.openapitools.client.models.ApiResponse.serializer()) - serializer.setMapper(org.openapitools.client.models.Category::class, org.openapitools.client.models.Category.serializer()) - serializer.setMapper(org.openapitools.client.models.Order::class, org.openapitools.client.models.Order.serializer()) - serializer.setMapper(org.openapitools.client.models.Pet::class, org.openapitools.client.models.Pet.serializer()) - serializer.setMapper(org.openapitools.client.models.Tag::class, org.openapitools.client.models.Tag.serializer()) - serializer.setMapper(org.openapitools.client.models.User::class, org.openapitools.client.models.User.serializer()) - } } /** @@ -155,11 +125,11 @@ open class ApiClient( else request(requestConfig, authNames = authNames) } - protected suspend inline fun request(requestConfig: RequestConfig, body: OutgoingContent = EmptyContent, authNames: kotlin.collections.List): HttpResponse { + protected suspend fun request(requestConfig: RequestConfig, body: OutgoingContent = EmptyContent, authNames: kotlin.collections.List): HttpResponse { requestConfig.updateForAuth(authNames) val headers = requestConfig.headers - return client.call { + return client.request { this.url { this.takeFrom(URLBuilder(baseUrl)) appendPath(requestConfig.path.trimStart('/').split('/')) @@ -174,7 +144,7 @@ open class ApiClient( if (requestConfig.method in listOf(RequestMethod.PUT, RequestMethod.POST, RequestMethod.PATCH)) this.body = body - }.response + } } private fun RequestConfig.updateForAuth(authNames: kotlin.collections.List) { @@ -199,13 +169,3 @@ open class ApiClient( RequestMethod.OPTIONS -> HttpMethod.Options } } - -// https://github.com/ktorio/ktor/issues/851 -private fun JsonSerializer.ignoreOutgoingContent() = IgnoreOutgoingContentJsonSerializer(this) - -private class IgnoreOutgoingContentJsonSerializer(private val delegate: JsonSerializer) : JsonSerializer by delegate { - override fun write(data: Any): OutgoingContent { - if (data is OutgoingContent) return data - return delegate.write(data) - } -} diff --git a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/Base64ByteArray.kt b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/Base64ByteArray.kt index 4bc1197cf00d..863ac385a4a5 100644 --- a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/Base64ByteArray.kt +++ b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/Base64ByteArray.kt @@ -1,13 +1,16 @@ package org.openapitools.client.infrastructure import kotlinx.serialization.* -import kotlinx.serialization.internal.StringDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder @Serializable class Base64ByteArray(val value: ByteArray) { @Serializer(Base64ByteArray::class) companion object : KSerializer { - override val descriptor = StringDescriptor.withName("Base64ByteArray") + override val descriptor = PrimitiveSerialDescriptor("Base64ByteArray", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, obj: Base64ByteArray) = encoder.encodeString(obj.value.encodeBase64()) override fun deserialize(decoder: Decoder) = Base64ByteArray(decoder.decodeString().decodeBase64Bytes()) } diff --git a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/Bytes.kt b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/Bytes.kt index 8a222416cf2d..b8f12a085298 100644 --- a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/Bytes.kt +++ b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/Bytes.kt @@ -1,6 +1,6 @@ package org.openapitools.client.infrastructure -import kotlinx.io.core.* +import io.ktor.utils.io.core.* import kotlin.experimental.and private val digits = "0123456789abcdef".toCharArray() @@ -32,7 +32,7 @@ internal fun hex(bytes: ByteArray): String { result[resultIndex++] = digits[b and 0x0f] } - return String(result) + return result.concatToString() } /** diff --git a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/HttpResponse.kt b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/HttpResponse.kt index c457eb4bce0b..61e55bc5b153 100644 --- a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/HttpResponse.kt +++ b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/HttpResponse.kt @@ -5,7 +5,7 @@ import io.ktor.client.call.typeInfo import io.ktor.http.Headers import io.ktor.http.isSuccess -open class HttpResponse(val response: io.ktor.client.response.HttpResponse, val provider: BodyProvider) { +open class HttpResponse(val response: io.ktor.client.statement.HttpResponse, val provider: BodyProvider) { val status: Int = response.status.value val success: Boolean = response.status.isSuccess() val headers: Map> = response.headers.mapEntries() @@ -22,29 +22,29 @@ open class HttpResponse(val response: io.ktor.client.response.HttpRespo } interface BodyProvider { - suspend fun body(response: io.ktor.client.response.HttpResponse): T - suspend fun typedBody(response: io.ktor.client.response.HttpResponse, type: TypeInfo): V + suspend fun body(response: io.ktor.client.statement.HttpResponse): T + suspend fun typedBody(response: io.ktor.client.statement.HttpResponse, type: TypeInfo): V } class TypedBodyProvider(private val type: TypeInfo) : BodyProvider { @Suppress("UNCHECKED_CAST") - override suspend fun body(response: io.ktor.client.response.HttpResponse): T = + override suspend fun body(response: io.ktor.client.statement.HttpResponse): T = response.call.receive(type) as T @Suppress("UNCHECKED_CAST") - override suspend fun typedBody(response: io.ktor.client.response.HttpResponse, type: TypeInfo): V = + override suspend fun typedBody(response: io.ktor.client.statement.HttpResponse, type: TypeInfo): V = response.call.receive(type) as V } class MappedBodyProvider(private val provider: BodyProvider, private val block: S.() -> T) : BodyProvider { - override suspend fun body(response: io.ktor.client.response.HttpResponse): T = + override suspend fun body(response: io.ktor.client.statement.HttpResponse): T = block(provider.body(response)) - override suspend fun typedBody(response: io.ktor.client.response.HttpResponse, type: TypeInfo): V = + override suspend fun typedBody(response: io.ktor.client.statement.HttpResponse, type: TypeInfo): V = provider.typedBody(response, type) } -inline fun io.ktor.client.response.HttpResponse.wrap(): HttpResponse = +inline fun io.ktor.client.statement.HttpResponse.wrap(): HttpResponse = HttpResponse(this, TypedBodyProvider(typeInfo())) fun HttpResponse.map(block: T.() -> V): HttpResponse = diff --git a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/OctetByteArray.kt b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/OctetByteArray.kt index 735e4e6e3f66..a7674acafc84 100644 --- a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/OctetByteArray.kt +++ b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/OctetByteArray.kt @@ -1,13 +1,16 @@ package org.openapitools.client.infrastructure import kotlinx.serialization.* -import kotlinx.serialization.internal.StringDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder @Serializable class OctetByteArray(val value: ByteArray) { @Serializer(OctetByteArray::class) companion object : KSerializer { - override val descriptor = StringDescriptor.withName("OctetByteArray") + override val descriptor = PrimitiveSerialDescriptor("OctetByteArray", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, obj: OctetByteArray) = encoder.encodeString(hex(obj.value)) override fun deserialize(decoder: Decoder) = OctetByteArray(hex(decoder.decodeString())) } diff --git a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/RequestConfig.kt b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/RequestConfig.kt index 7e948e1dd071..0f2790f370e2 100644 --- a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/RequestConfig.kt +++ b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/infrastructure/RequestConfig.kt @@ -8,10 +8,10 @@ package org.openapitools.client.infrastructure * NOTE: Headers is a Map because rfc2616 defines * multi-valued headers as csv-only. */ -data class RequestConfig( +data class RequestConfig( val method: RequestMethod, val path: String, val headers: MutableMap = mutableMapOf(), val query: MutableMap> = mutableMapOf(), - val body: T? = null + val body: kotlin.Any? = null ) \ No newline at end of file diff --git a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/ApiResponse.kt b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/ApiResponse.kt index a035628a8f93..495762848cfc 100644 --- a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/ApiResponse.kt +++ b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/ApiResponse.kt @@ -13,7 +13,6 @@ package org.openapitools.client.models import kotlinx.serialization.* -import kotlinx.serialization.internal.CommonEnumSerializer /** * Describes the result of uploading an image resource diff --git a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/Category.kt b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/Category.kt index d5f9a45fd4de..f15292ac556a 100644 --- a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/Category.kt +++ b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/Category.kt @@ -13,7 +13,6 @@ package org.openapitools.client.models import kotlinx.serialization.* -import kotlinx.serialization.internal.CommonEnumSerializer /** * A category for a pet diff --git a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/Order.kt b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/Order.kt index 0a53ba0740e4..055aeaff3c43 100644 --- a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/Order.kt +++ b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/Order.kt @@ -13,7 +13,6 @@ package org.openapitools.client.models import kotlinx.serialization.* -import kotlinx.serialization.internal.CommonEnumSerializer /** * An order for a pets from the pet store @@ -39,10 +38,11 @@ data class Order ( * Order Status * Values: placed,approved,delivered */ + @Serializable enum class Status(val value: kotlin.String) { - placed("placed"), - approved("approved"), - delivered("delivered"); + @SerialName(value = "placed") placed("placed"), + @SerialName(value = "approved") approved("approved"), + @SerialName(value = "delivered") delivered("delivered"); } } diff --git a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/Pet.kt b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/Pet.kt index 1649cf0fb293..682f183793db 100644 --- a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/Pet.kt +++ b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/Pet.kt @@ -15,7 +15,6 @@ import org.openapitools.client.models.Category import org.openapitools.client.models.Tag import kotlinx.serialization.* -import kotlinx.serialization.internal.CommonEnumSerializer /** * A pet for sale in the pet store @@ -41,10 +40,11 @@ data class Pet ( * pet status in the store * Values: available,pending,sold */ + @Serializable enum class Status(val value: kotlin.String) { - available("available"), - pending("pending"), - sold("sold"); + @SerialName(value = "available") available("available"), + @SerialName(value = "pending") pending("pending"), + @SerialName(value = "sold") sold("sold"); } } diff --git a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/Tag.kt b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/Tag.kt index 6116e50d3f92..17789668a2ae 100644 --- a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/Tag.kt +++ b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/Tag.kt @@ -13,7 +13,6 @@ package org.openapitools.client.models import kotlinx.serialization.* -import kotlinx.serialization.internal.CommonEnumSerializer /** * A tag for a pet diff --git a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/User.kt b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/User.kt index 97b53a049c1d..f43915ba5cc8 100644 --- a/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/User.kt +++ b/samples/client/petstore/kotlin-multiplatform/src/commonMain/kotlin/org/openapitools/client/models/User.kt @@ -13,7 +13,6 @@ package org.openapitools.client.models import kotlinx.serialization.* -import kotlinx.serialization.internal.CommonEnumSerializer /** * A User who is purchasing from the pet store