[Kotlin Multiplatform] Update and fixes for Kotlin 1.5.10 and Kotlinx.serialization 1.2.1 (#9755)

* Update Kotlin Multiplatform with Kotlin 1.5.10, Ktor 1.6.0 and Kotlinx.serialization 1.2.1
* remove @Serializable from interfaces
* Using 'String(CharArray): String' is an error. Use CharArray.concatToString() instead
* Fix, RequestConfig needs a type to infer type variable T

Fixes from @DevSrSouzaern
* Fix `private` keyword not being handle as a reservedWords
* Fix enum serialization generation
* Migrate gradle build to Kotlin DSL

* update samples and documentation

* PR Review changes
* sample update
* revert non multiplatform kotlinx_serialization removal
* default Json{} in ApiClient
* revert accidental version push for jvm client
* Match ktor and Kotlinx Serialization version in documentation and build.gradle.kts

* remove const from JSON_DEFAULT

* Update AbstractKotlinCodegen.java

Co-authored-by: Gabriel Souza <devsrsouza@gmail.com>
Co-authored-by: ern <ern@ti8m.ch>
This commit is contained in:
Matthias Ernst
2021-07-03 17:33:39 +02:00
committed by GitHub
parent 173c7ca652
commit 17b6379df5
44 changed files with 392 additions and 603 deletions

View File

@@ -16,27 +16,19 @@ 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
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
class PetApi @UseExperimental(UnstableDefault::class) constructor(
baseUrl: kotlin.String = "http://petstore.swagger.io/v2",
class PetApi(
baseUrl: String = ApiClient.BASE_URL,
httpClientEngine: HttpClientEngine? = null,
serializer: KotlinxSerializer
) : 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)))
jsonSerializer: Json = ApiClient.JSON_DEFAULT
) : ApiClient(baseUrl, httpClientEngine, jsonSerializer) {
/**
* Add a new pet to the store
@@ -54,7 +46,7 @@ class PetApi @UseExperimental(UnstableDefault::class) constructor(
val localVariableHeaders = mutableMapOf<String, String>()
val localVariableConfig = RequestConfig(
val localVariableConfig = RequestConfig<kotlin.Any?>(
RequestMethod.POST,
"/pet",
query = localVariableQuery,
@@ -89,7 +81,7 @@ class PetApi @UseExperimental(UnstableDefault::class) constructor(
val localVariableHeaders = mutableMapOf<String, String>()
apiKey?.apply { localVariableHeaders["api_key"] = this.toString() }
val localVariableConfig = RequestConfig(
val localVariableConfig = RequestConfig<kotlin.Any?>(
RequestMethod.DELETE,
"/pet/{petId}".replace("{" + "petId" + "}", "$petId"),
query = localVariableQuery,
@@ -123,7 +115,7 @@ class PetApi @UseExperimental(UnstableDefault::class) constructor(
val localVariableHeaders = mutableMapOf<String, String>()
val localVariableConfig = RequestConfig(
val localVariableConfig = RequestConfig<kotlin.Any?>(
RequestMethod.GET,
"/pet/findByStatus",
query = localVariableQuery,
@@ -141,10 +133,10 @@ class PetApi @UseExperimental(UnstableDefault::class) constructor(
private class FindPetsByStatusResponse(val value: List<Pet>) {
@Serializer(FindPetsByStatusResponse::class)
companion object : KSerializer<FindPetsByStatusResponse> {
private val serializer: KSerializer<List<Pet>> = Pet.serializer().list
override val descriptor = StringDescriptor.withName("FindPetsByStatusResponse")
override fun serialize(encoder: Encoder, obj: FindPetsByStatusResponse) = serializer.serialize(encoder, obj.value)
override fun deserialize(decoder: Decoder) = FindPetsByStatusResponse(serializer.deserialize(decoder))
private val serializer: KSerializer<List<Pet>> = serializer<List<Pet>>()
override val descriptor = serializer.descriptor
override fun serialize(encoder: Encoder, obj: FindPetsByStatusResponse) = serializer.serialize(encoder, obj.value)
override fun deserialize(decoder: Decoder) = FindPetsByStatusResponse(serializer.deserialize(decoder))
}
}
@@ -167,7 +159,7 @@ class PetApi @UseExperimental(UnstableDefault::class) constructor(
val localVariableHeaders = mutableMapOf<String, String>()
val localVariableConfig = RequestConfig(
val localVariableConfig = RequestConfig<kotlin.Any?>(
RequestMethod.GET,
"/pet/findByTags",
query = localVariableQuery,
@@ -185,10 +177,10 @@ class PetApi @UseExperimental(UnstableDefault::class) constructor(
private class FindPetsByTagsResponse(val value: List<Pet>) {
@Serializer(FindPetsByTagsResponse::class)
companion object : KSerializer<FindPetsByTagsResponse> {
private val serializer: KSerializer<List<Pet>> = Pet.serializer().list
override val descriptor = StringDescriptor.withName("FindPetsByTagsResponse")
override fun serialize(encoder: Encoder, obj: FindPetsByTagsResponse) = serializer.serialize(encoder, obj.value)
override fun deserialize(decoder: Decoder) = FindPetsByTagsResponse(serializer.deserialize(decoder))
private val serializer: KSerializer<List<Pet>> = serializer<List<Pet>>()
override val descriptor = serializer.descriptor
override fun serialize(encoder: Encoder, obj: FindPetsByTagsResponse) = serializer.serialize(encoder, obj.value)
override fun deserialize(decoder: Decoder) = FindPetsByTagsResponse(serializer.deserialize(decoder))
}
}
@@ -210,7 +202,7 @@ class PetApi @UseExperimental(UnstableDefault::class) constructor(
val localVariableHeaders = mutableMapOf<String, String>()
val localVariableConfig = RequestConfig(
val localVariableConfig = RequestConfig<kotlin.Any?>(
RequestMethod.GET,
"/pet/{petId}".replace("{" + "petId" + "}", "$petId"),
query = localVariableQuery,
@@ -241,7 +233,7 @@ class PetApi @UseExperimental(UnstableDefault::class) constructor(
val localVariableHeaders = mutableMapOf<String, String>()
val localVariableConfig = RequestConfig(
val localVariableConfig = RequestConfig<kotlin.Any?>(
RequestMethod.PUT,
"/pet",
query = localVariableQuery,
@@ -279,7 +271,7 @@ class PetApi @UseExperimental(UnstableDefault::class) constructor(
val localVariableHeaders = mutableMapOf<String, String>()
val localVariableConfig = RequestConfig(
val localVariableConfig = RequestConfig<kotlin.Any?>(
RequestMethod.POST,
"/pet/{petId}".replace("{" + "petId" + "}", "$petId"),
query = localVariableQuery,
@@ -317,7 +309,7 @@ class PetApi @UseExperimental(UnstableDefault::class) constructor(
val localVariableHeaders = mutableMapOf<String, String>()
val localVariableConfig = RequestConfig(
val localVariableConfig = RequestConfig<kotlin.Any?>(
RequestMethod.POST,
"/pet/{petId}/uploadImage".replace("{" + "petId" + "}", "$petId"),
query = localVariableQuery,
@@ -332,13 +324,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())
}
}
}

View File

@@ -15,27 +15,19 @@ 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
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
class StoreApi @UseExperimental(UnstableDefault::class) constructor(
baseUrl: kotlin.String = "http://petstore.swagger.io/v2",
class StoreApi(
baseUrl: String = ApiClient.BASE_URL,
httpClientEngine: HttpClientEngine? = null,
serializer: KotlinxSerializer
) : 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)))
jsonSerializer: Json = ApiClient.JSON_DEFAULT
) : ApiClient(baseUrl, httpClientEngine, jsonSerializer) {
/**
* Delete purchase order by ID
@@ -54,7 +46,7 @@ class StoreApi @UseExperimental(UnstableDefault::class) constructor(
val localVariableHeaders = mutableMapOf<String, String>()
val localVariableConfig = RequestConfig(
val localVariableConfig = RequestConfig<kotlin.Any?>(
RequestMethod.DELETE,
"/store/order/{orderId}".replace("{" + "orderId" + "}", "$orderId"),
query = localVariableQuery,
@@ -86,7 +78,7 @@ class StoreApi @UseExperimental(UnstableDefault::class) constructor(
val localVariableHeaders = mutableMapOf<String, String>()
val localVariableConfig = RequestConfig(
val localVariableConfig = RequestConfig<kotlin.Any?>(
RequestMethod.GET,
"/store/inventory",
query = localVariableQuery,
@@ -104,10 +96,10 @@ class StoreApi @UseExperimental(UnstableDefault::class) constructor(
private class GetInventoryResponse(val value: Map<kotlin.String, kotlin.Int>) {
@Serializer(GetInventoryResponse::class)
companion object : KSerializer<GetInventoryResponse> {
private val serializer: KSerializer<Map<kotlin.String, kotlin.Int>> = (kotlin.String.serializer() to kotlin.Int.serializer()).map
override val descriptor = StringDescriptor.withName("GetInventoryResponse")
override fun serialize(encoder: Encoder, obj: GetInventoryResponse) = serializer.serialize(encoder, obj.value)
override fun deserialize(decoder: Decoder) = GetInventoryResponse(serializer.deserialize(decoder))
private val serializer: KSerializer<Map<kotlin.String, kotlin.Int>> = serializer<Map<String, kotlin.Int>>()
override val descriptor = serializer.descriptor
override fun serialize(encoder: Encoder, obj: GetInventoryResponse) = serializer.serialize(encoder, obj.value)
override fun deserialize(decoder: Decoder) = GetInventoryResponse(serializer.deserialize(decoder))
}
}
@@ -129,7 +121,7 @@ class StoreApi @UseExperimental(UnstableDefault::class) constructor(
val localVariableHeaders = mutableMapOf<String, String>()
val localVariableConfig = RequestConfig(
val localVariableConfig = RequestConfig<kotlin.Any?>(
RequestMethod.GET,
"/store/order/{orderId}".replace("{" + "orderId" + "}", "$orderId"),
query = localVariableQuery,
@@ -161,7 +153,7 @@ class StoreApi @UseExperimental(UnstableDefault::class) constructor(
val localVariableHeaders = mutableMapOf<String, String>()
val localVariableConfig = RequestConfig(
val localVariableConfig = RequestConfig<kotlin.Any?>(
RequestMethod.POST,
"/store/order",
query = localVariableQuery,
@@ -177,11 +169,4 @@ class StoreApi @UseExperimental(UnstableDefault::class) constructor(
companion object {
internal fun setMappers(serializer: KotlinxSerializer) {
serializer.setMapper(GetInventoryResponse::class, GetInventoryResponse.serializer())
}
}
}

View File

@@ -15,27 +15,19 @@ 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
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
class UserApi @UseExperimental(UnstableDefault::class) constructor(
baseUrl: kotlin.String = "http://petstore.swagger.io/v2",
class UserApi(
baseUrl: String = ApiClient.BASE_URL,
httpClientEngine: HttpClientEngine? = null,
serializer: KotlinxSerializer
) : 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)))
jsonSerializer: Json = ApiClient.JSON_DEFAULT
) : ApiClient(baseUrl, httpClientEngine, jsonSerializer) {
/**
* Create user
@@ -53,7 +45,7 @@ class UserApi @UseExperimental(UnstableDefault::class) constructor(
val localVariableHeaders = mutableMapOf<String, String>()
val localVariableConfig = RequestConfig(
val localVariableConfig = RequestConfig<kotlin.Any?>(
RequestMethod.POST,
"/user",
query = localVariableQuery,
@@ -85,7 +77,7 @@ class UserApi @UseExperimental(UnstableDefault::class) constructor(
val localVariableHeaders = mutableMapOf<String, String>()
val localVariableConfig = RequestConfig(
val localVariableConfig = RequestConfig<kotlin.Any?>(
RequestMethod.POST,
"/user/createWithArray",
query = localVariableQuery,
@@ -103,10 +95,10 @@ class UserApi @UseExperimental(UnstableDefault::class) constructor(
private class CreateUsersWithArrayInputRequest(val value: List<User>) {
@Serializer(CreateUsersWithArrayInputRequest::class)
companion object : KSerializer<CreateUsersWithArrayInputRequest> {
private val serializer: KSerializer<List<User>> = User.serializer().list
override val descriptor = StringDescriptor.withName("CreateUsersWithArrayInputRequest")
override fun serialize(encoder: Encoder, obj: CreateUsersWithArrayInputRequest) = serializer.serialize(encoder, obj.value)
override fun deserialize(decoder: Decoder) = CreateUsersWithArrayInputRequest(serializer.deserialize(decoder))
private val serializer: KSerializer<List<User>> = serializer<List<User>>()
override val descriptor = serializer.descriptor
override fun serialize(encoder: Encoder, obj: CreateUsersWithArrayInputRequest) = serializer.serialize(encoder, obj.value)
override fun deserialize(decoder: Decoder) = CreateUsersWithArrayInputRequest(serializer.deserialize(decoder))
}
}
@@ -126,7 +118,7 @@ class UserApi @UseExperimental(UnstableDefault::class) constructor(
val localVariableHeaders = mutableMapOf<String, String>()
val localVariableConfig = RequestConfig(
val localVariableConfig = RequestConfig<kotlin.Any?>(
RequestMethod.POST,
"/user/createWithList",
query = localVariableQuery,
@@ -144,10 +136,10 @@ class UserApi @UseExperimental(UnstableDefault::class) constructor(
private class CreateUsersWithListInputRequest(val value: List<User>) {
@Serializer(CreateUsersWithListInputRequest::class)
companion object : KSerializer<CreateUsersWithListInputRequest> {
private val serializer: KSerializer<List<User>> = User.serializer().list
override val descriptor = StringDescriptor.withName("CreateUsersWithListInputRequest")
override fun serialize(encoder: Encoder, obj: CreateUsersWithListInputRequest) = serializer.serialize(encoder, obj.value)
override fun deserialize(decoder: Decoder) = CreateUsersWithListInputRequest(serializer.deserialize(decoder))
private val serializer: KSerializer<List<User>> = serializer<List<User>>()
override val descriptor = serializer.descriptor
override fun serialize(encoder: Encoder, obj: CreateUsersWithListInputRequest) = serializer.serialize(encoder, obj.value)
override fun deserialize(decoder: Decoder) = CreateUsersWithListInputRequest(serializer.deserialize(decoder))
}
}
@@ -168,7 +160,7 @@ class UserApi @UseExperimental(UnstableDefault::class) constructor(
val localVariableHeaders = mutableMapOf<String, String>()
val localVariableConfig = RequestConfig(
val localVariableConfig = RequestConfig<kotlin.Any?>(
RequestMethod.DELETE,
"/user/{username}".replace("{" + "username" + "}", "$username"),
query = localVariableQuery,
@@ -201,7 +193,7 @@ class UserApi @UseExperimental(UnstableDefault::class) constructor(
val localVariableHeaders = mutableMapOf<String, String>()
val localVariableConfig = RequestConfig(
val localVariableConfig = RequestConfig<kotlin.Any?>(
RequestMethod.GET,
"/user/{username}".replace("{" + "username" + "}", "$username"),
query = localVariableQuery,
@@ -237,7 +229,7 @@ class UserApi @UseExperimental(UnstableDefault::class) constructor(
val localVariableHeaders = mutableMapOf<String, String>()
val localVariableConfig = RequestConfig(
val localVariableConfig = RequestConfig<kotlin.Any?>(
RequestMethod.GET,
"/user/login",
query = localVariableQuery,
@@ -268,7 +260,7 @@ class UserApi @UseExperimental(UnstableDefault::class) constructor(
val localVariableHeaders = mutableMapOf<String, String>()
val localVariableConfig = RequestConfig(
val localVariableConfig = RequestConfig<kotlin.Any?>(
RequestMethod.GET,
"/user/logout",
query = localVariableQuery,
@@ -300,7 +292,7 @@ class UserApi @UseExperimental(UnstableDefault::class) constructor(
val localVariableHeaders = mutableMapOf<String, String>()
val localVariableConfig = RequestConfig(
val localVariableConfig = RequestConfig<kotlin.Any?>(
RequestMethod.PUT,
"/user/{username}".replace("{" + "username" + "}", "$username"),
query = localVariableQuery,
@@ -316,13 +308,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())
}
}
}

View File

@@ -2,24 +2,21 @@ package org.openapitools.client.infrastructure
import io.ktor.client.HttpClient
import io.ktor.client.HttpClientConfig
import io.ktor.client.call.call
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.*
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,17 +25,11 @@ 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 json: Json
) {
private val serializer: JsonSerializer by lazy {
serializer.apply { setMappers(this) }.ignoreOutgoingContent()
KotlinxSerializer(json).ignoreOutgoingContent()
}
private val client: HttpClient by lazy {
@@ -53,23 +44,9 @@ open class ApiClient(
}
companion object {
const val BASE_URL = "http://petstore.swagger.io/v2"
val JSON_DEFAULT = Json { ignoreUnknownKeys = true }
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())
}
}
/**
@@ -140,26 +117,26 @@ open class ApiClient(
auth.bearerToken = bearerToken
}
protected suspend fun multipartFormRequest(requestConfig: RequestConfig, body: kotlin.collections.List<PartData>?, authNames: kotlin.collections.List<String>): HttpResponse {
protected suspend fun <T: Any?> multipartFormRequest(requestConfig: RequestConfig<T>, body: kotlin.collections.List<PartData>?, authNames: kotlin.collections.List<String>): HttpResponse {
return request(requestConfig, MultiPartFormDataContent(body ?: listOf()), authNames)
}
protected suspend fun urlEncodedFormRequest(requestConfig: RequestConfig, body: Parameters?, authNames: kotlin.collections.List<String>): HttpResponse {
protected suspend fun <T: Any?> urlEncodedFormRequest(requestConfig: RequestConfig<T>, body: Parameters?, authNames: kotlin.collections.List<String>): HttpResponse {
return request(requestConfig, FormDataContent(body ?: Parameters.Empty), authNames)
}
protected suspend fun jsonRequest(requestConfig: RequestConfig, body: Any? = null, authNames: kotlin.collections.List<String>): HttpResponse {
protected suspend fun <T: Any?> jsonRequest(requestConfig: RequestConfig<T>, body: Any? = null, authNames: kotlin.collections.List<String>): HttpResponse {
val contentType = (requestConfig.headers[HttpHeaders.ContentType]?.let { ContentType.parse(it) }
?: ContentType.Application.Json)
return if (body != null) request(requestConfig, serializer.write(body, contentType), authNames)
else request(requestConfig, authNames = authNames)
}
protected suspend inline fun <reified T: Any?> request(requestConfig: RequestConfig<T>, body: OutgoingContent = EmptyContent, authNames: kotlin.collections.List<String>): HttpResponse {
requestConfig.updateForAuth(authNames)
protected suspend fun <T: Any?> request(requestConfig: RequestConfig<T>, body: OutgoingContent = EmptyContent, authNames: kotlin.collections.List<String>): HttpResponse {
requestConfig.updateForAuth<T>(authNames)
val headers = requestConfig.headers
return client.call {
return client.request<HttpResponse> {
this.url {
this.takeFrom(URLBuilder(baseUrl))
appendPath(requestConfig.path.trimStart('/').split('/'))
@@ -174,10 +151,10 @@ 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<String>) {
private fun <T: Any?> RequestConfig<T>.updateForAuth(authNames: kotlin.collections.List<String>) {
for (authName in authNames) {
val auth = authentications?.get(authName) ?: throw Exception("Authentication undefined: $authName")
auth.apply(query, headers)

View File

@@ -1,13 +1,14 @@
package org.openapitools.client.infrastructure
import kotlinx.serialization.*
import kotlinx.serialization.internal.StringDescriptor
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
@Serializable
class Base64ByteArray(val value: ByteArray) {
@Serializer(Base64ByteArray::class)
companion object : KSerializer<Base64ByteArray> {
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())
}

View File

@@ -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()
}
/**

View File

@@ -5,7 +5,7 @@ import io.ktor.client.call.typeInfo
import io.ktor.http.Headers
import io.ktor.http.isSuccess
open class HttpResponse<T : Any>(val response: io.ktor.client.response.HttpResponse, val provider: BodyProvider<T>) {
open class HttpResponse<T : Any>(val response: io.ktor.client.statement.HttpResponse, val provider: BodyProvider<T>) {
val status: Int = response.status.value
val success: Boolean = response.status.isSuccess()
val headers: Map<String, List<String>> = response.headers.mapEntries()
@@ -22,29 +22,29 @@ open class HttpResponse<T : Any>(val response: io.ktor.client.response.HttpRespo
}
interface BodyProvider<T : Any> {
suspend fun body(response: io.ktor.client.response.HttpResponse): T
suspend fun <V : Any> typedBody(response: io.ktor.client.response.HttpResponse, type: TypeInfo): V
suspend fun body(response: io.ktor.client.statement.HttpResponse): T
suspend fun <V : Any> typedBody(response: io.ktor.client.statement.HttpResponse, type: TypeInfo): V
}
class TypedBodyProvider<T : Any>(private val type: TypeInfo) : BodyProvider<T> {
@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 <V : Any> typedBody(response: io.ktor.client.response.HttpResponse, type: TypeInfo): V =
override suspend fun <V : Any> typedBody(response: io.ktor.client.statement.HttpResponse, type: TypeInfo): V =
response.call.receive(type) as V
}
class MappedBodyProvider<S : Any, T : Any>(private val provider: BodyProvider<S>, private val block: S.() -> T) : BodyProvider<T> {
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 <V : Any> typedBody(response: io.ktor.client.response.HttpResponse, type: TypeInfo): V =
override suspend fun <V : Any> typedBody(response: io.ktor.client.statement.HttpResponse, type: TypeInfo): V =
provider.typedBody(response, type)
}
inline fun <reified T : Any> io.ktor.client.response.HttpResponse.wrap(): HttpResponse<T> =
inline fun <reified T : Any> io.ktor.client.statement.HttpResponse.wrap(): HttpResponse<T> =
HttpResponse(this, TypedBodyProvider(typeInfo<T>()))
fun <T : Any, V : Any> HttpResponse<T>.map(block: T.() -> V): HttpResponse<V> =

View File

@@ -1,13 +1,14 @@
package org.openapitools.client.infrastructure
import kotlinx.serialization.*
import kotlinx.serialization.internal.StringDescriptor
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
@Serializable
class OctetByteArray(val value: ByteArray) {
@Serializer(OctetByteArray::class)
companion object : KSerializer<OctetByteArray> {
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()))
}

View File

@@ -13,7 +13,8 @@ package org.openapitools.client.models
import kotlinx.serialization.*
import kotlinx.serialization.internal.CommonEnumSerializer
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
/**
* Describes the result of uploading an image resource

View File

@@ -13,7 +13,8 @@ package org.openapitools.client.models
import kotlinx.serialization.*
import kotlinx.serialization.internal.CommonEnumSerializer
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
/**
* A category for a pet

View File

@@ -13,7 +13,8 @@ package org.openapitools.client.models
import kotlinx.serialization.*
import kotlinx.serialization.internal.CommonEnumSerializer
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
/**
* An order for a pets from the pet store
@@ -39,10 +40,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");
}
}

View File

@@ -15,7 +15,8 @@ import org.openapitools.client.models.Category
import org.openapitools.client.models.Tag
import kotlinx.serialization.*
import kotlinx.serialization.internal.CommonEnumSerializer
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
/**
* A pet for sale in the pet store
@@ -41,10 +42,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");
}
}

View File

@@ -13,7 +13,8 @@ package org.openapitools.client.models
import kotlinx.serialization.*
import kotlinx.serialization.internal.CommonEnumSerializer
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
/**
* A tag for a pet

View File

@@ -13,7 +13,8 @@ package org.openapitools.client.models
import kotlinx.serialization.*
import kotlinx.serialization.internal.CommonEnumSerializer
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
/**
* A User who is purchasing from the pet store