From 87dc75780a83033e7c51fdccbba3ee80e8b7dc4b Mon Sep 17 00:00:00 2001 From: Bruno Coelho <4brunu@users.noreply.github.com> Date: Tue, 26 Jul 2022 09:42:19 +0100 Subject: [PATCH] [kotlin][client] add support for unknown default case with Kotlinx Serialization (#12930) * [kotlin][client] Kotlinx Serialization cleanup * [kotlin][client] Kotlinx Serialization cleanup * [kotlin][client] add support for unknown default case with Kotlinx Serialization * [kotlin][client] add support for unknown default case with Kotlinx Serialization * [kotlin][client] add support for unknown default case with Kotlinx Serialization * [kotlin][client] improve Kotlinx Serialization naming * [kotlin][client] improve Kotlinx Serialization naming --- bin/configs/kotlin-json-request-string.yaml | 2 + bin/configs/kotlin-uppercase-enum.yaml | 2 + .../kotlin-client/data_class.mustache | 26 ++++++++- .../kotlin-client/enum_class.mustache | 26 ++++++++- .../LocalDateAdapter.kt.mustache | 2 +- .../LocalDateTimeAdapter.kt.mustache | 2 +- .../OffsetDateTimeAdapter.kt.mustache | 2 +- .../infrastructure/Serializer.kt.mustache | 20 ++++++- .../infrastructure/URIAdapter.kt.mustache | 2 +- .../infrastructure/UUIDAdapter.kt.mustache | 2 +- .../infrastructure/ApiClient.kt.mustache | 8 +-- .../infrastructure/ApiClient.kt.mustache | 4 +- .../.openapi-generator/FILES | 7 ++- .../kotlin-json-request-string/build.gradle | 12 +++- .../proguard-rules.pro | 11 ++++ .../org/openapitools/client/apis/PetApi.kt | 3 +- .../org/openapitools/client/apis/StoreApi.kt | 3 +- .../org/openapitools/client/apis/UserApi.kt | 3 +- .../client/infrastructure/ApiClient.kt | 8 +-- .../infrastructure/AtomicBooleanAdapter.kt | 21 +++++++ .../infrastructure/AtomicIntegerAdapter.kt | 21 +++++++ .../infrastructure/AtomicLongAdapter.kt | 21 +++++++ .../infrastructure/BigDecimalAdapter.kt | 24 ++++---- .../infrastructure/BigIntegerAdapter.kt | 23 +++++--- .../client/infrastructure/ByteArrayAdapter.kt | 12 ---- .../client/infrastructure/LocalDateAdapter.kt | 25 ++++---- .../infrastructure/LocalDateTimeAdapter.kt | 25 ++++---- .../infrastructure/OffsetDateTimeAdapter.kt | 25 ++++---- .../client/infrastructure/Serializer.kt | 57 ++++++++++++++----- .../infrastructure/StringBuilderAdapter.kt | 20 +++++++ .../client/infrastructure/URIAdapter.kt | 22 ++++--- .../client/infrastructure/URLAdapter.kt | 21 +++++++ .../client/infrastructure/UUIDAdapter.kt | 24 +++++--- .../openapitools/client/models/Category.kt | 15 +++-- .../client/models/ModelApiResponse.kt | 17 ++++-- .../org/openapitools/client/models/Order.kt | 48 ++++++++++++---- .../org/openapitools/client/models/Pet.kt | 48 ++++++++++++---- .../org/openapitools/client/models/Tag.kt | 15 +++-- .../org/openapitools/client/models/User.kt | 27 +++++---- .../client/infrastructure/ApiClient.kt | 4 +- .../client/infrastructure/Serializer.kt | 20 ++++++- .../.openapi-generator/FILES | 7 ++- .../kotlin-uppercase-enum/build.gradle | 12 +++- .../kotlin-uppercase-enum/docs/PetEnum.md | 2 + .../kotlin-uppercase-enum/proguard-rules.pro | 11 ++++ .../org/openapitools/client/apis/EnumApi.kt | 3 +- .../client/infrastructure/ApiClient.kt | 10 ++-- .../infrastructure/AtomicBooleanAdapter.kt | 21 +++++++ .../infrastructure/AtomicIntegerAdapter.kt | 21 +++++++ .../infrastructure/AtomicLongAdapter.kt | 21 +++++++ .../infrastructure/BigDecimalAdapter.kt | 24 ++++---- .../infrastructure/BigIntegerAdapter.kt | 23 +++++--- .../client/infrastructure/ByteArrayAdapter.kt | 12 ---- .../client/infrastructure/LocalDateAdapter.kt | 25 ++++---- .../infrastructure/LocalDateTimeAdapter.kt | 25 ++++---- .../infrastructure/OffsetDateTimeAdapter.kt | 25 ++++---- .../client/infrastructure/Serializer.kt | 57 ++++++++++++++----- .../infrastructure/StringBuilderAdapter.kt | 20 +++++++ .../client/infrastructure/URIAdapter.kt | 22 ++++--- .../client/infrastructure/URLAdapter.kt | 21 +++++++ .../client/infrastructure/UUIDAdapter.kt | 24 +++++--- .../org/openapitools/client/models/PetEnum.kt | 36 ++++++++++-- 62 files changed, 825 insertions(+), 277 deletions(-) create mode 100644 samples/client/petstore/kotlin-json-request-string/proguard-rules.pro create mode 100644 samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/AtomicBooleanAdapter.kt create mode 100644 samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/AtomicIntegerAdapter.kt create mode 100644 samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/AtomicLongAdapter.kt delete mode 100644 samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt create mode 100644 samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/StringBuilderAdapter.kt create mode 100644 samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/URLAdapter.kt create mode 100644 samples/client/petstore/kotlin-uppercase-enum/proguard-rules.pro create mode 100644 samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/AtomicBooleanAdapter.kt create mode 100644 samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/AtomicIntegerAdapter.kt create mode 100644 samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/AtomicLongAdapter.kt delete mode 100644 samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt create mode 100644 samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/StringBuilderAdapter.kt create mode 100644 samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/URLAdapter.kt diff --git a/bin/configs/kotlin-json-request-string.yaml b/bin/configs/kotlin-json-request-string.yaml index bbe5ddd4283..31943045ab6 100644 --- a/bin/configs/kotlin-json-request-string.yaml +++ b/bin/configs/kotlin-json-request-string.yaml @@ -7,3 +7,5 @@ additionalProperties: artifactId: kotlin-petstore-json-request-string parcelizeModels: true supportAndroidApiLevel25AndBelow: true + serializationLibrary: kotlinx_serialization + enumUnknownDefaultCase: "true" diff --git a/bin/configs/kotlin-uppercase-enum.yaml b/bin/configs/kotlin-uppercase-enum.yaml index b3501dd8af9..f4066ef7db9 100644 --- a/bin/configs/kotlin-uppercase-enum.yaml +++ b/bin/configs/kotlin-uppercase-enum.yaml @@ -5,3 +5,5 @@ templateDir: modules/openapi-generator/src/main/resources/kotlin-client additionalProperties: artifactId: kotlin-uppercase-enum enumPropertyNaming: UPPERCASE + serializationLibrary: kotlinx_serialization + enumUnknownDefaultCase: "true" 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 5f5b4da03ca..8d2c28acd4a 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 @@ -19,6 +19,13 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo import {{#serializableModel}}kotlinx.serialization.Serializable as KSerializable{{/serializableModel}}{{^serializableModel}}kotlinx.serialization.Serializable{{/serializableModel}} import kotlinx.serialization.SerialName import kotlinx.serialization.Contextual +{{#enumUnknownDefaultCase}} +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +{{/enumUnknownDefaultCase}} {{#hasEnums}} {{/hasEnums}} {{/kotlinx_serialization}} @@ -88,7 +95,7 @@ import {{packageName}}.infrastructure.ITransformForStorage */ {{^multiplatform}} {{#kotlinx_serialization}} - {{#serializableModel}}@KSerializable{{/serializableModel}}{{^serializableModel}}@Serializable{{/serializableModel}} + {{#serializableModel}}@KSerializable{{/serializableModel}}{{^serializableModel}}@Serializable{{#enumUnknownDefaultCase}}(with = {{classname}}Serializer::class){{/enumUnknownDefaultCase}}{{/serializableModel}} {{/kotlinx_serialization}} {{/multiplatform}} {{#multiplatform}} @@ -116,7 +123,22 @@ import {{packageName}}.infrastructure.ITransformForStorage {{/multiplatform}} {{/enumVars}} {{/allowableValues}} - } + }{{#kotlinx_serialization}}{{#enumUnknownDefaultCase}} + + @Serializer(forClass = {{{nameInCamelCase}}}::class) + internal object {{nameInCamelCase}}Serializer : KSerializer<{{nameInCamelCase}}> { + override val descriptor = {{{dataType}}}.serializer().descriptor + + override fun deserialize(decoder: Decoder): {{nameInCamelCase}} { + val value = decoder.decodeSerializableValue({{{dataType}}}.serializer()) + return {{nameInCamelCase}}.values().firstOrNull { it.value == value } + ?: {{nameInCamelCase}}.{{#allowableValues}}{{#enumVars}}{{#-last}}{{&name}}{{/-last}}{{/enumVars}}{{/allowableValues}} + } + + override fun serialize(encoder: Encoder, value: {{nameInCamelCase}}) { + encoder.encodeSerializableValue({{{dataType}}}.serializer(), value.value) + } + }{{/enumUnknownDefaultCase}}{{/kotlinx_serialization}} {{/isEnum}} {{/vars}} {{/hasEnums}} 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 fcdcd87ffa9..4d11f8f2653 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 @@ -11,6 +11,13 @@ import com.fasterxml.jackson.annotation.JsonProperty {{#kotlinx_serialization}} import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +{{#enumUnknownDefaultCase}} +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +{{/enumUnknownDefaultCase}} {{/kotlinx_serialization}} {{/multiplatform}} {{#multiplatform}} @@ -22,7 +29,7 @@ import kotlinx.serialization.* * * Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}} */ -{{#multiplatform}}@Serializable{{/multiplatform}}{{#kotlinx_serialization}}@Serializable{{/kotlinx_serialization}} +{{#multiplatform}}@Serializable{{/multiplatform}}{{#kotlinx_serialization}}@Serializable{{#enumUnknownDefaultCase}}(with = {{classname}}Serializer::class){{/enumUnknownDefaultCase}}{{/kotlinx_serialization}} {{#nonPublicApi}}internal {{/nonPublicApi}}enum class {{classname}}(val value: {{{dataType}}}) { {{#allowableValues}}{{#enumVars}} {{^multiplatform}} @@ -79,4 +86,19 @@ import kotlinx.serialization.* } } } -} +}{{#kotlinx_serialization}}{{#enumUnknownDefaultCase}} + +@Serializer(forClass = {{classname}}::class) +internal object {{classname}}Serializer : KSerializer<{{classname}}> { + override val descriptor = {{{dataType}}}.serializer().descriptor + + override fun deserialize(decoder: Decoder): {{classname}} { + val value = decoder.decodeSerializableValue({{{dataType}}}.serializer()) + return {{classname}}.values().firstOrNull { it.value == value } + ?: {{classname}}.{{#allowableValues}}{{#enumVars}}{{#-last}}{{&name}}{{/-last}}{{/enumVars}}{{/allowableValues}} + } + + override fun serialize(encoder: Encoder, value: {{classname}}) { + encoder.encodeSerializableValue({{{dataType}}}.serializer(), value.value) + } +}{{/enumUnknownDefaultCase}}{{/kotlinx_serialization}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/LocalDateAdapter.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/LocalDateAdapter.kt.mustache index 97b5fd66190..cdcf444ec32 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/LocalDateAdapter.kt.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/LocalDateAdapter.kt.mustache @@ -72,7 +72,7 @@ import org.threeten.bp.format.DateTimeFormatter {{/gson}} {{#kotlinx_serialization}} @Serializer(forClass = LocalDate::class) -object LocalDateAdapter : KSerializer { +{{#nonPublicApi}}internal {{/nonPublicApi}}object LocalDateAdapter : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocalDate", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: LocalDate) { diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/LocalDateTimeAdapter.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/LocalDateTimeAdapter.kt.mustache index 3608ddb0db5..8d793d1ff42 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/LocalDateTimeAdapter.kt.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/LocalDateTimeAdapter.kt.mustache @@ -72,7 +72,7 @@ import org.threeten.bp.format.DateTimeFormatter {{/gson}} {{#kotlinx_serialization}} @Serializer(forClass = LocalDateTime::class) -object LocalDateTimeAdapter : KSerializer { +{{#nonPublicApi}}internal {{/nonPublicApi}}object LocalDateTimeAdapter : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: LocalDateTime) { diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/OffsetDateTimeAdapter.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/OffsetDateTimeAdapter.kt.mustache index 855b4c87df6..fff7ded5c28 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/OffsetDateTimeAdapter.kt.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/OffsetDateTimeAdapter.kt.mustache @@ -72,7 +72,7 @@ import org.threeten.bp.format.DateTimeFormatter {{/gson}} {{#kotlinx_serialization}} @Serializer(forClass = OffsetDateTime::class) -object OffsetDateTimeAdapter : KSerializer { +{{#nonPublicApi}}internal {{/nonPublicApi}}object OffsetDateTimeAdapter : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("OffsetDateTime", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: OffsetDateTime) { diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/Serializer.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/Serializer.kt.mustache index 884e16846b1..31200465728 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/Serializer.kt.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/Serializer.kt.mustache @@ -98,8 +98,13 @@ import java.util.concurrent.atomic.AtomicLong .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false) {{/jackson}} {{#kotlinx_serialization}} + @Deprecated("Use Serializer.kotlinxSerializationAdapters instead", replaceWith = ReplaceWith("Serializer.kotlinxSerializationAdapters")) @JvmStatic - val kotlinSerializationAdapters = SerializersModule { + val kotlinSerializationAdapters: SerializersModule + get() { return kotlinxSerializationAdapters } + + @JvmStatic + val kotlinxSerializationAdapters = SerializersModule { contextual(BigDecimal::class, BigDecimalAdapter) contextual(BigInteger::class, BigIntegerAdapter) contextual(LocalDate::class, LocalDateAdapter) @@ -114,7 +119,18 @@ import java.util.concurrent.atomic.AtomicLong contextual(StringBuilder::class, StringBuilderAdapter) } + @Deprecated("Use Serializer.kotlinxSerializationJson instead", replaceWith = ReplaceWith("Serializer.kotlinxSerializationJson")) @JvmStatic - val jvmJson: Json by lazy { Json { serializersModule = kotlinSerializationAdapters } } + val jvmJson: Json + get() { return kotlinxSerializationJson } + + @JvmStatic + val kotlinxSerializationJson: Json by lazy { + Json { + serializersModule = kotlinxSerializationAdapters + ignoreUnknownKeys = true + isLenient = true + } + } {{/kotlinx_serialization}} } diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/URIAdapter.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/URIAdapter.kt.mustache index c9582955553..2fae6a3b6bc 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/URIAdapter.kt.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/URIAdapter.kt.mustache @@ -26,7 +26,7 @@ import java.net.URI {{/moshi}} {{#kotlinx_serialization}} @Serializer(forClass = URI::class) -object URIAdapter : KSerializer { +{{#nonPublicApi}}internal {{/nonPublicApi}}object URIAdapter : KSerializer { override fun serialize(encoder: Encoder, value: URI) { encoder.encodeString(value.toASCIIString()) } diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/UUIDAdapter.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/UUIDAdapter.kt.mustache index ea903c36ca9..d0ec45c471d 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/UUIDAdapter.kt.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/UUIDAdapter.kt.mustache @@ -26,7 +26,7 @@ import java.util.UUID {{/moshi}} {{#kotlinx_serialization}} @Serializer(forClass = UUID::class) -object UUIDAdapter : KSerializer { +{{#nonPublicApi}}internal {{/nonPublicApi}}object UUIDAdapter : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("UUID", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: UUID) { diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ApiClient.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ApiClient.kt.mustache index 32b20282811..d61913ce869 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ApiClient.kt.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ApiClient.kt.mustache @@ -169,7 +169,7 @@ import com.squareup.moshi.adapter MediaType.parse(mediaType ?: JsonMediaType), Serializer.jacksonObjectMapper.writeValueAsString(content) {{/jackson}} {{#kotlinx_serialization}} - MediaType.parse(mediaType ?: JsonMediaType), Serializer.jvmJson.encodeToString(content) + MediaType.parse(mediaType ?: JsonMediaType), Serializer.kotlinxSerializationJson.encodeToString(content) {{/kotlinx_serialization}} ) } @@ -188,7 +188,7 @@ import com.squareup.moshi.adapter Serializer.jacksonObjectMapper.writeValueAsString(content) {{/jackson}} {{#kotlinx_serialization}} - Serializer.jvmJson.encodeToString(content) + Serializer.kotlinxSerializationJson.encodeToString(content) {{/kotlinx_serialization}} .toRequestBody((mediaType ?: JsonMediaType).toMediaTypeOrNull()) } @@ -236,7 +236,7 @@ import com.squareup.moshi.adapter {{#moshi}}Serializer.moshi.adapter().fromJson(bodyContent){{/moshi}}{{! }}{{#gson}}Serializer.gson.fromJson(bodyContent, (object: TypeToken(){}).getType()){{/gson}}{{! }}{{#jackson}}Serializer.jacksonObjectMapper.readValue(bodyContent, object: TypeReference() {}){{/jackson}}{{! - }}{{#kotlinx_serialization}}Serializer.jvmJson.decodeFromString(bodyContent){{/kotlinx_serialization}} + }}{{#kotlinx_serialization}}Serializer.kotlinxSerializationJson.decodeFromString(bodyContent){{/kotlinx_serialization}} else -> throw UnsupportedOperationException("responseBody currently only supports JSON body.") } } @@ -432,7 +432,7 @@ import com.squareup.moshi.adapter return Serializer.jacksonObjectMapper.writeValueAsString(value).replace("\"", "") {{/jackson}} {{#kotlinx_serialization}} - return Serializer.jvmJson.encodeToString(value).replace("\"", "") + return Serializer.kotlinxSerializationJson.encodeToString(value).replace("\"", "") {{/kotlinx_serialization}} {{/toJson}} {{^toJson}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/infrastructure/ApiClient.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/infrastructure/ApiClient.kt.mustache index 4146c154b2d..4b48bdcb7da 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/infrastructure/ApiClient.kt.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/infrastructure/ApiClient.kt.mustache @@ -51,7 +51,7 @@ import retrofit2.converter.moshi.MoshiConverterFactory {{#kotlinx_serialization}} import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory -import {{packageName}}.infrastructure.Serializer.jvmJson +import {{packageName}}.infrastructure.Serializer.kotlinxSerializationJson import okhttp3.MediaType.Companion.toMediaType {{/kotlinx_serialization}} @@ -84,7 +84,7 @@ import okhttp3.MediaType.Companion.toMediaType .addConverterFactory(MoshiConverterFactory.create(serializerBuilder.build())) {{/moshi}} {{#kotlinx_serialization}} - .addConverterFactory(jvmJson.asConverterFactory("application/json".toMediaType())) + .addConverterFactory(kotlinxSerializationJson.asConverterFactory("application/json".toMediaType())) {{/kotlinx_serialization}} .apply { if (converterFactory != null) { diff --git a/samples/client/petstore/kotlin-json-request-string/.openapi-generator/FILES b/samples/client/petstore/kotlin-json-request-string/.openapi-generator/FILES index ab27444a312..4ed261ac1a0 100644 --- a/samples/client/petstore/kotlin-json-request-string/.openapi-generator/FILES +++ b/samples/client/petstore/kotlin-json-request-string/.openapi-generator/FILES @@ -13,6 +13,7 @@ gradle/wrapper/gradle-wrapper.jar gradle/wrapper/gradle-wrapper.properties gradlew gradlew.bat +proguard-rules.pro settings.gradle src/main/kotlin/org/openapitools/client/apis/PetApi.kt src/main/kotlin/org/openapitools/client/apis/StoreApi.kt @@ -20,9 +21,11 @@ src/main/kotlin/org/openapitools/client/apis/UserApi.kt src/main/kotlin/org/openapitools/client/infrastructure/ApiAbstractions.kt src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt src/main/kotlin/org/openapitools/client/infrastructure/ApiResponse.kt +src/main/kotlin/org/openapitools/client/infrastructure/AtomicBooleanAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/AtomicIntegerAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/AtomicLongAdapter.kt src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt -src/main/kotlin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt src/main/kotlin/org/openapitools/client/infrastructure/Errors.kt src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt @@ -32,7 +35,9 @@ src/main/kotlin/org/openapitools/client/infrastructure/RequestConfig.kt src/main/kotlin/org/openapitools/client/infrastructure/RequestMethod.kt src/main/kotlin/org/openapitools/client/infrastructure/ResponseExtensions.kt src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt +src/main/kotlin/org/openapitools/client/infrastructure/StringBuilderAdapter.kt src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/URLAdapter.kt src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt src/main/kotlin/org/openapitools/client/models/Category.kt src/main/kotlin/org/openapitools/client/models/ModelApiResponse.kt diff --git a/samples/client/petstore/kotlin-json-request-string/build.gradle b/samples/client/petstore/kotlin-json-request-string/build.gradle index 614bd17172a..602832bb247 100644 --- a/samples/client/petstore/kotlin-json-request-string/build.gradle +++ b/samples/client/petstore/kotlin-json-request-string/build.gradle @@ -14,11 +14,13 @@ buildscript { } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" } } apply plugin: 'kotlin' apply plugin: 'kotlin-parcelize' +apply plugin: 'kotlinx-serialization' repositories { maven { url "https://repo1.maven.org/maven2" } @@ -30,9 +32,13 @@ test { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" - implementation "com.squareup.moshi:moshi-kotlin:1.12.0" - implementation "com.squareup.moshi:moshi-adapters:1.12.0" + implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.1" implementation "com.squareup.okhttp3:okhttp:4.9.1" testImplementation "io.kotlintest:kotlintest-runner-junit5:3.4.2" } + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { + kotlinOptions { + freeCompilerArgs += "-Xopt-in=kotlinx.serialization.ExperimentalSerializationApi" + } +} diff --git a/samples/client/petstore/kotlin-json-request-string/proguard-rules.pro b/samples/client/petstore/kotlin-json-request-string/proguard-rules.pro new file mode 100644 index 00000000000..7c7b08bf381 --- /dev/null +++ b/samples/client/petstore/kotlin-json-request-string/proguard-rules.pro @@ -0,0 +1,11 @@ +-keepattributes *Annotation*, InnerClasses +-dontnote kotlinx.serialization.AnnotationsKt # core serialization annotations + +# kotlinx-serialization-json specific. Add this if you have java.lang.NoClassDefFoundError kotlinx.serialization.json.JsonObjectSerializer +-keepclassmembers class kotlinx.serialization.json.** { *** Companion; } +-keepclasseswithmembers class kotlinx.serialization.json.** { kotlinx.serialization.KSerializer serializer(...); } + +# project specific. +-keep,includedescriptorclasses class org.openapitools.client.models.**$$serializer { *; } +-keepclassmembers class org.openapitools.client.models.** { *** Companion; } +-keepclasseswithmembers class org.openapitools.client.models.** { kotlinx.serialization.KSerializer serializer(...); } diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/apis/PetApi.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/apis/PetApi.kt index 4ae59dbd260..3f02a9e0e6f 100644 --- a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/apis/PetApi.kt +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/apis/PetApi.kt @@ -26,7 +26,8 @@ import okhttp3.OkHttpClient import org.openapitools.client.models.ModelApiResponse import org.openapitools.client.models.Pet -import com.squareup.moshi.Json +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable import org.openapitools.client.infrastructure.ApiClient import org.openapitools.client.infrastructure.ApiResponse diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/apis/StoreApi.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/apis/StoreApi.kt index d192191c850..d951868b34c 100644 --- a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/apis/StoreApi.kt +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/apis/StoreApi.kt @@ -25,7 +25,8 @@ import okhttp3.OkHttpClient import org.openapitools.client.models.Order -import com.squareup.moshi.Json +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable import org.openapitools.client.infrastructure.ApiClient import org.openapitools.client.infrastructure.ApiResponse diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/apis/UserApi.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/apis/UserApi.kt index 327a69c8e7e..8e96a200f7d 100644 --- a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/apis/UserApi.kt +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/apis/UserApi.kt @@ -25,7 +25,8 @@ import okhttp3.OkHttpClient import org.openapitools.client.models.User -import com.squareup.moshi.Json +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable import org.openapitools.client.infrastructure.ApiClient import org.openapitools.client.infrastructure.ApiResponse diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index 804c66706c2..d692b5fad98 100644 --- a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -28,7 +28,8 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale -import com.squareup.moshi.adapter +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.encodeToString open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -105,7 +106,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie if (content == null) { EMPTY_REQUEST } else { - Serializer.moshi.adapter(T::class.java).toJson(content) + Serializer.kotlinxSerializationJson.encodeToString(content) .toRequestBody((mediaType ?: JsonMediaType).toMediaTypeOrNull()) } mediaType == XmlMediaType -> throw UnsupportedOperationException("xml not currently supported.") @@ -113,7 +114,6 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie else -> throw UnsupportedOperationException("requestBody currently only supports JSON body and File body.") } - @OptIn(ExperimentalStdlibApi::class) protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { if(body == null) { return null @@ -140,7 +140,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie } return when { mediaType==null || (mediaType.startsWith("application/") && mediaType.endsWith("json")) -> - Serializer.moshi.adapter().fromJson(bodyContent) + Serializer.kotlinxSerializationJson.decodeFromString(bodyContent) else -> throw UnsupportedOperationException("responseBody currently only supports JSON body.") } } diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/AtomicBooleanAdapter.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/AtomicBooleanAdapter.kt new file mode 100644 index 00000000000..80611e349b1 --- /dev/null +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/AtomicBooleanAdapter.kt @@ -0,0 +1,21 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.util.concurrent.atomic.AtomicBoolean + +@Serializer(forClass = AtomicBoolean::class) +object AtomicBooleanAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: AtomicBoolean) { + encoder.encodeBoolean(value.get()) + } + + override fun deserialize(decoder: Decoder): AtomicBoolean = AtomicBoolean(decoder.decodeBoolean()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("AtomicBoolean", PrimitiveKind.BOOLEAN) +} diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/AtomicIntegerAdapter.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/AtomicIntegerAdapter.kt new file mode 100644 index 00000000000..8a5a8bafc78 --- /dev/null +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/AtomicIntegerAdapter.kt @@ -0,0 +1,21 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.util.concurrent.atomic.AtomicInteger + +@Serializer(forClass = AtomicInteger::class) +object AtomicIntegerAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: AtomicInteger) { + encoder.encodeInt(value.get()) + } + + override fun deserialize(decoder: Decoder): AtomicInteger = AtomicInteger(decoder.decodeInt()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("AtomicInteger", PrimitiveKind.INT) +} diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/AtomicLongAdapter.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/AtomicLongAdapter.kt new file mode 100644 index 00000000000..5842c490889 --- /dev/null +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/AtomicLongAdapter.kt @@ -0,0 +1,21 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.util.concurrent.atomic.AtomicLong + +@Serializer(forClass = AtomicLong::class) +object AtomicLongAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: AtomicLong) { + encoder.encodeLong(value.get()) + } + + override fun deserialize(decoder: Decoder): AtomicLong = AtomicLong(decoder.decodeLong()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("AtomicLong", PrimitiveKind.LONG) +} diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt index 064b57fc6b8..94cbcb573ae 100644 --- a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt @@ -1,17 +1,17 @@ package org.openapitools.client.infrastructure -import com.squareup.moshi.FromJson -import com.squareup.moshi.ToJson +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor import java.math.BigDecimal -class BigDecimalAdapter { - @ToJson - fun toJson(value: BigDecimal): String { - return value.toPlainString() - } - - @FromJson - fun fromJson(value: String): BigDecimal { - return BigDecimal(value) - } +@Serializer(forClass = BigDecimal::class) +object BigDecimalAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("BigDecimal", PrimitiveKind.STRING) + override fun deserialize(decoder: Decoder): BigDecimal = BigDecimal(decoder.decodeString()) + override fun serialize(encoder: Encoder, value: BigDecimal) = encoder.encodeString(value.toPlainString()) } diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt index 7df6057b450..8f0544aa2b8 100644 --- a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt @@ -1,17 +1,22 @@ package org.openapitools.client.infrastructure -import com.squareup.moshi.FromJson -import com.squareup.moshi.ToJson +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor import java.math.BigInteger -class BigIntegerAdapter { - @ToJson - fun toJson(value: BigInteger): String { - return value.toString() +@Serializer(forClass = BigInteger::class) +object BigIntegerAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("BigInteger", PrimitiveKind.STRING) + override fun deserialize(decoder: Decoder): BigInteger { + return BigInteger(decoder.decodeString()) } - @FromJson - fun fromJson(value: String): BigInteger { - return BigInteger(value) + override fun serialize(encoder: Encoder, value: BigInteger) { + encoder.encodeString(value.toString()) } } diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt deleted file mode 100644 index ff5e2a81ee8..00000000000 --- a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt +++ /dev/null @@ -1,12 +0,0 @@ -package org.openapitools.client.infrastructure - -import com.squareup.moshi.FromJson -import com.squareup.moshi.ToJson - -class ByteArrayAdapter { - @ToJson - fun toJson(data: ByteArray): String = String(data) - - @FromJson - fun fromJson(data: String): ByteArray = data.toByteArray() -} diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt index b2e1654479a..f7c632d6964 100644 --- a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt @@ -1,19 +1,24 @@ package org.openapitools.client.infrastructure -import com.squareup.moshi.FromJson -import com.squareup.moshi.ToJson +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor import java.time.LocalDate import java.time.format.DateTimeFormatter -class LocalDateAdapter { - @ToJson - fun toJson(value: LocalDate): String { - return DateTimeFormatter.ISO_LOCAL_DATE.format(value) +@Serializer(forClass = LocalDate::class) +object LocalDateAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocalDate", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: LocalDate) { + encoder.encodeString(DateTimeFormatter.ISO_LOCAL_DATE.format(value)) } - @FromJson - fun fromJson(value: String): LocalDate { - return LocalDate.parse(value, DateTimeFormatter.ISO_LOCAL_DATE) + override fun deserialize(decoder: Decoder): LocalDate { + return LocalDate.parse(decoder.decodeString(), DateTimeFormatter.ISO_LOCAL_DATE) } - } diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt index e082db94811..88bd1401139 100644 --- a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt @@ -1,19 +1,24 @@ package org.openapitools.client.infrastructure -import com.squareup.moshi.FromJson -import com.squareup.moshi.ToJson +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor import java.time.LocalDateTime import java.time.format.DateTimeFormatter -class LocalDateTimeAdapter { - @ToJson - fun toJson(value: LocalDateTime): String { - return DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(value) +@Serializer(forClass = LocalDateTime::class) +object LocalDateTimeAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: LocalDateTime) { + encoder.encodeString(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(value)) } - @FromJson - fun fromJson(value: String): LocalDateTime { - return LocalDateTime.parse(value, DateTimeFormatter.ISO_LOCAL_DATE_TIME) + override fun deserialize(decoder: Decoder): LocalDateTime { + return LocalDateTime.parse(decoder.decodeString(), DateTimeFormatter.ISO_LOCAL_DATE_TIME) } - } diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt index 87437871a31..e0fe9e3b532 100644 --- a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt @@ -1,19 +1,24 @@ package org.openapitools.client.infrastructure -import com.squareup.moshi.FromJson -import com.squareup.moshi.ToJson +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor import java.time.OffsetDateTime import java.time.format.DateTimeFormatter -class OffsetDateTimeAdapter { - @ToJson - fun toJson(value: OffsetDateTime): String { - return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(value) +@Serializer(forClass = OffsetDateTime::class) +object OffsetDateTimeAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("OffsetDateTime", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: OffsetDateTime) { + encoder.encodeString(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(value)) } - @FromJson - fun fromJson(value: String): OffsetDateTime { - return OffsetDateTime.parse(value, DateTimeFormatter.ISO_OFFSET_DATE_TIME) + override fun deserialize(decoder: Decoder): OffsetDateTime { + return OffsetDateTime.parse(decoder.decodeString(), DateTimeFormatter.ISO_OFFSET_DATE_TIME) } - } diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt index e22592e47d7..82473d228a0 100644 --- a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt @@ -1,23 +1,52 @@ package org.openapitools.client.infrastructure -import com.squareup.moshi.Moshi -import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory +import java.math.BigDecimal +import java.math.BigInteger +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.OffsetDateTime +import java.util.UUID +import kotlinx.serialization.json.Json +import kotlinx.serialization.modules.SerializersModule +import java.net.URI +import java.net.URL +import java.util.concurrent.atomic.AtomicBoolean +import java.util.concurrent.atomic.AtomicInteger +import java.util.concurrent.atomic.AtomicLong object Serializer { + @Deprecated("Use Serializer.kotlinxSerializationAdapters instead", replaceWith = ReplaceWith("Serializer.kotlinxSerializationAdapters")) @JvmStatic - val moshiBuilder: Moshi.Builder = Moshi.Builder() - .add(OffsetDateTimeAdapter()) - .add(LocalDateTimeAdapter()) - .add(LocalDateAdapter()) - .add(UUIDAdapter()) - .add(ByteArrayAdapter()) - .add(URIAdapter()) - .add(KotlinJsonAdapterFactory()) - .add(BigDecimalAdapter()) - .add(BigIntegerAdapter()) + val kotlinSerializationAdapters: SerializersModule + get() { return kotlinxSerializationAdapters } @JvmStatic - val moshi: Moshi by lazy { - moshiBuilder.build() + val kotlinxSerializationAdapters = SerializersModule { + contextual(BigDecimal::class, BigDecimalAdapter) + contextual(BigInteger::class, BigIntegerAdapter) + contextual(LocalDate::class, LocalDateAdapter) + contextual(LocalDateTime::class, LocalDateTimeAdapter) + contextual(OffsetDateTime::class, OffsetDateTimeAdapter) + contextual(UUID::class, UUIDAdapter) + contextual(AtomicInteger::class, AtomicIntegerAdapter) + contextual(AtomicLong::class, AtomicLongAdapter) + contextual(AtomicBoolean::class, AtomicBooleanAdapter) + contextual(URI::class, URIAdapter) + contextual(URL::class, URLAdapter) + contextual(StringBuilder::class, StringBuilderAdapter) + } + + @Deprecated("Use Serializer.kotlinxSerializationJson instead", replaceWith = ReplaceWith("Serializer.kotlinxSerializationJson")) + @JvmStatic + val jvmJson: Json + get() { return kotlinxSerializationJson } + + @JvmStatic + val kotlinxSerializationJson: Json by lazy { + Json { + serializersModule = kotlinxSerializationAdapters + ignoreUnknownKeys = true + isLenient = true + } } } diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/StringBuilderAdapter.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/StringBuilderAdapter.kt new file mode 100644 index 00000000000..7a15749f062 --- /dev/null +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/StringBuilderAdapter.kt @@ -0,0 +1,20 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor + +@Serializer(forClass = StringBuilder::class) +object StringBuilderAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: StringBuilder) { + encoder.encodeString(value.toString()) + } + + override fun deserialize(decoder: Decoder): StringBuilder = StringBuilder(decoder.decodeString()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("StringBuilder", PrimitiveKind.STRING) +} diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt index 927522757da..0856c99813c 100644 --- a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt @@ -1,13 +1,21 @@ package org.openapitools.client.infrastructure -import com.squareup.moshi.FromJson -import com.squareup.moshi.ToJson +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor import java.net.URI -class URIAdapter { - @ToJson - fun toJson(uri: URI) = uri.toString() +@Serializer(forClass = URI::class) +object URIAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: URI) { + encoder.encodeString(value.toASCIIString()) + } - @FromJson - fun fromJson(s: String): URI = URI.create(s) + override fun deserialize(decoder: Decoder): URI = URI(decoder.decodeString()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("URI", PrimitiveKind.STRING) } diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/URLAdapter.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/URLAdapter.kt new file mode 100644 index 00000000000..0dead7a73f8 --- /dev/null +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/URLAdapter.kt @@ -0,0 +1,21 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.net.URL + +@Serializer(forClass = URL::class) +object URLAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: URL) { + encoder.encodeString(value.toExternalForm()) + } + + override fun deserialize(decoder: Decoder): URL = URL(decoder.decodeString()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("URL", PrimitiveKind.STRING) +} diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt index 7ccf7dc25d2..fbae87c1a6c 100644 --- a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt @@ -1,13 +1,23 @@ package org.openapitools.client.infrastructure -import com.squareup.moshi.FromJson -import com.squareup.moshi.ToJson +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor import java.util.UUID -class UUIDAdapter { - @ToJson - fun toJson(uuid: UUID) = uuid.toString() +@Serializer(forClass = UUID::class) +object UUIDAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("UUID", PrimitiveKind.STRING) - @FromJson - fun fromJson(s: String): UUID = UUID.fromString(s) + override fun serialize(encoder: Encoder, value: UUID) { + encoder.encodeString(value.toString()) + } + + override fun deserialize(decoder: Decoder): UUID { + return UUID.fromString(decoder.decodeString()) + } } diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/Category.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/Category.kt index 51c35a061e1..ff869ccdb55 100644 --- a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/Category.kt +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/Category.kt @@ -21,7 +21,14 @@ package org.openapitools.client.models -import com.squareup.moshi.Json +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder import android.os.Parcelable import kotlinx.parcelize.Parcelize @@ -32,13 +39,13 @@ import kotlinx.parcelize.Parcelize * @param name */ @Parcelize - +@Serializable data class Category ( - @Json(name = "id") + @SerialName(value = "id") val id: kotlin.Long? = null, - @Json(name = "name") + @SerialName(value = "name") val name: kotlin.String? = null ) : Parcelable diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/ModelApiResponse.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/ModelApiResponse.kt index 61b35faee86..ca993b1baee 100644 --- a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/ModelApiResponse.kt +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/ModelApiResponse.kt @@ -21,7 +21,14 @@ package org.openapitools.client.models -import com.squareup.moshi.Json +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder import android.os.Parcelable import kotlinx.parcelize.Parcelize @@ -33,16 +40,16 @@ import kotlinx.parcelize.Parcelize * @param message */ @Parcelize - +@Serializable data class ModelApiResponse ( - @Json(name = "code") + @SerialName(value = "code") val code: kotlin.Int? = null, - @Json(name = "type") + @SerialName(value = "type") val type: kotlin.String? = null, - @Json(name = "message") + @SerialName(value = "message") val message: kotlin.String? = null ) : Parcelable diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/Order.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/Order.kt index e2bfdd701d1..39d53fb50a8 100644 --- a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/Order.kt +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/Order.kt @@ -21,7 +21,14 @@ package org.openapitools.client.models -import com.squareup.moshi.Json +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder import android.os.Parcelable import kotlinx.parcelize.Parcelize @@ -36,26 +43,26 @@ import kotlinx.parcelize.Parcelize * @param complete */ @Parcelize - +@Serializable data class Order ( - @Json(name = "id") + @SerialName(value = "id") val id: kotlin.Long? = null, - @Json(name = "petId") + @SerialName(value = "petId") val petId: kotlin.Long? = null, - @Json(name = "quantity") + @SerialName(value = "quantity") val quantity: kotlin.Int? = null, - @Json(name = "shipDate") + @Contextual @SerialName(value = "shipDate") val shipDate: java.time.OffsetDateTime? = null, /* Order Status */ - @Json(name = "status") + @SerialName(value = "status") val status: Order.Status? = null, - @Json(name = "complete") + @SerialName(value = "complete") val complete: kotlin.Boolean? = false ) : Parcelable { @@ -63,12 +70,29 @@ data class Order ( /** * Order Status * - * Values: placed,approved,delivered + * Values: placed,approved,delivered,unknownDefaultOpenApi */ + @Serializable(with = OrderSerializer::class) enum class Status(val value: kotlin.String) { - @Json(name = "placed") placed("placed"), - @Json(name = "approved") approved("approved"), - @Json(name = "delivered") delivered("delivered"); + @SerialName(value = "placed") placed("placed"), + @SerialName(value = "approved") approved("approved"), + @SerialName(value = "delivered") delivered("delivered"), + @SerialName(value = "unknown_default_open_api") unknownDefaultOpenApi("unknown_default_open_api"); + } + + @Serializer(forClass = Status::class) + internal object StatusSerializer : KSerializer { + override val descriptor = kotlin.String.serializer().descriptor + + override fun deserialize(decoder: Decoder): Status { + val value = decoder.decodeSerializableValue(kotlin.String.serializer()) + return Status.values().firstOrNull { it.value == value } + ?: Status.unknownDefaultOpenApi + } + + override fun serialize(encoder: Encoder, value: Status) { + encoder.encodeSerializableValue(kotlin.String.serializer(), value.value) + } } } diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/Pet.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/Pet.kt index 6ff38c8e0d5..727e95d5a3a 100644 --- a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/Pet.kt +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/Pet.kt @@ -23,7 +23,14 @@ package org.openapitools.client.models import org.openapitools.client.models.Category import org.openapitools.client.models.Tag -import com.squareup.moshi.Json +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder import android.os.Parcelable import kotlinx.parcelize.Parcelize @@ -38,26 +45,26 @@ import kotlinx.parcelize.Parcelize * @param status pet status in the store */ @Parcelize - +@Serializable data class Pet ( - @Json(name = "name") + @SerialName(value = "name") val name: kotlin.String, - @Json(name = "photoUrls") + @SerialName(value = "photoUrls") val photoUrls: kotlin.collections.List, - @Json(name = "id") + @SerialName(value = "id") val id: kotlin.Long? = null, - @Json(name = "category") + @SerialName(value = "category") val category: Category? = null, - @Json(name = "tags") + @SerialName(value = "tags") val tags: kotlin.collections.List? = null, /* pet status in the store */ - @Json(name = "status") + @SerialName(value = "status") val status: Pet.Status? = null ) : Parcelable { @@ -65,12 +72,29 @@ data class Pet ( /** * pet status in the store * - * Values: available,pending,sold + * Values: available,pending,sold,unknownDefaultOpenApi */ + @Serializable(with = PetSerializer::class) enum class Status(val value: kotlin.String) { - @Json(name = "available") available("available"), - @Json(name = "pending") pending("pending"), - @Json(name = "sold") sold("sold"); + @SerialName(value = "available") available("available"), + @SerialName(value = "pending") pending("pending"), + @SerialName(value = "sold") sold("sold"), + @SerialName(value = "unknown_default_open_api") unknownDefaultOpenApi("unknown_default_open_api"); + } + + @Serializer(forClass = Status::class) + internal object StatusSerializer : KSerializer { + override val descriptor = kotlin.String.serializer().descriptor + + override fun deserialize(decoder: Decoder): Status { + val value = decoder.decodeSerializableValue(kotlin.String.serializer()) + return Status.values().firstOrNull { it.value == value } + ?: Status.unknownDefaultOpenApi + } + + override fun serialize(encoder: Encoder, value: Status) { + encoder.encodeSerializableValue(kotlin.String.serializer(), value.value) + } } } diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/Tag.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/Tag.kt index 18421bb3ac3..ff5eb529b14 100644 --- a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/Tag.kt +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/Tag.kt @@ -21,7 +21,14 @@ package org.openapitools.client.models -import com.squareup.moshi.Json +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder import android.os.Parcelable import kotlinx.parcelize.Parcelize @@ -32,13 +39,13 @@ import kotlinx.parcelize.Parcelize * @param name */ @Parcelize - +@Serializable data class Tag ( - @Json(name = "id") + @SerialName(value = "id") val id: kotlin.Long? = null, - @Json(name = "name") + @SerialName(value = "name") val name: kotlin.String? = null ) : Parcelable diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/User.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/User.kt index 22889800c03..26180326a0a 100644 --- a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/User.kt +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/models/User.kt @@ -21,7 +21,14 @@ package org.openapitools.client.models -import com.squareup.moshi.Json +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder import android.os.Parcelable import kotlinx.parcelize.Parcelize @@ -38,32 +45,32 @@ import kotlinx.parcelize.Parcelize * @param userStatus User Status */ @Parcelize - +@Serializable data class User ( - @Json(name = "id") + @SerialName(value = "id") val id: kotlin.Long? = null, - @Json(name = "username") + @SerialName(value = "username") val username: kotlin.String? = null, - @Json(name = "firstName") + @SerialName(value = "firstName") val firstName: kotlin.String? = null, - @Json(name = "lastName") + @SerialName(value = "lastName") val lastName: kotlin.String? = null, - @Json(name = "email") + @SerialName(value = "email") val email: kotlin.String? = null, - @Json(name = "password") + @SerialName(value = "password") val password: kotlin.String? = null, - @Json(name = "phone") + @SerialName(value = "phone") val phone: kotlin.String? = null, /* User Status */ - @Json(name = "userStatus") + @SerialName(value = "userStatus") val userStatus: kotlin.Int? = null ) : Parcelable diff --git a/samples/client/petstore/kotlin-retrofit2-kotlinx_serialization/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-retrofit2-kotlinx_serialization/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index ed22d5d071e..2cc80d48407 100644 --- a/samples/client/petstore/kotlin-retrofit2-kotlinx_serialization/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-retrofit2-kotlinx_serialization/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -16,7 +16,7 @@ import retrofit2.Converter import retrofit2.converter.scalars.ScalarsConverterFactory import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory -import org.openapitools.client.infrastructure.Serializer.jvmJson +import org.openapitools.client.infrastructure.Serializer.kotlinxSerializationJson import okhttp3.MediaType.Companion.toMediaType class ApiClient( @@ -32,7 +32,7 @@ class ApiClient( Retrofit.Builder() .baseUrl(baseUrl) .addConverterFactory(ScalarsConverterFactory.create()) - .addConverterFactory(jvmJson.asConverterFactory("application/json".toMediaType())) + .addConverterFactory(kotlinxSerializationJson.asConverterFactory("application/json".toMediaType())) .apply { if (converterFactory != null) { addConverterFactory(converterFactory) diff --git a/samples/client/petstore/kotlin-retrofit2-kotlinx_serialization/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt b/samples/client/petstore/kotlin-retrofit2-kotlinx_serialization/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt index bbb13638034..82473d228a0 100644 --- a/samples/client/petstore/kotlin-retrofit2-kotlinx_serialization/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt +++ b/samples/client/petstore/kotlin-retrofit2-kotlinx_serialization/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt @@ -15,8 +15,13 @@ import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicLong object Serializer { + @Deprecated("Use Serializer.kotlinxSerializationAdapters instead", replaceWith = ReplaceWith("Serializer.kotlinxSerializationAdapters")) @JvmStatic - val kotlinSerializationAdapters = SerializersModule { + val kotlinSerializationAdapters: SerializersModule + get() { return kotlinxSerializationAdapters } + + @JvmStatic + val kotlinxSerializationAdapters = SerializersModule { contextual(BigDecimal::class, BigDecimalAdapter) contextual(BigInteger::class, BigIntegerAdapter) contextual(LocalDate::class, LocalDateAdapter) @@ -31,6 +36,17 @@ object Serializer { contextual(StringBuilder::class, StringBuilderAdapter) } + @Deprecated("Use Serializer.kotlinxSerializationJson instead", replaceWith = ReplaceWith("Serializer.kotlinxSerializationJson")) @JvmStatic - val jvmJson: Json by lazy { Json { serializersModule = kotlinSerializationAdapters } } + val jvmJson: Json + get() { return kotlinxSerializationJson } + + @JvmStatic + val kotlinxSerializationJson: Json by lazy { + Json { + serializersModule = kotlinxSerializationAdapters + ignoreUnknownKeys = true + isLenient = true + } + } } diff --git a/samples/client/petstore/kotlin-uppercase-enum/.openapi-generator/FILES b/samples/client/petstore/kotlin-uppercase-enum/.openapi-generator/FILES index 9a212390c6b..9139e88c885 100644 --- a/samples/client/petstore/kotlin-uppercase-enum/.openapi-generator/FILES +++ b/samples/client/petstore/kotlin-uppercase-enum/.openapi-generator/FILES @@ -6,14 +6,17 @@ gradle/wrapper/gradle-wrapper.jar gradle/wrapper/gradle-wrapper.properties gradlew gradlew.bat +proguard-rules.pro settings.gradle src/main/kotlin/org/openapitools/client/apis/EnumApi.kt src/main/kotlin/org/openapitools/client/infrastructure/ApiAbstractions.kt src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt src/main/kotlin/org/openapitools/client/infrastructure/ApiResponse.kt +src/main/kotlin/org/openapitools/client/infrastructure/AtomicBooleanAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/AtomicIntegerAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/AtomicLongAdapter.kt src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt -src/main/kotlin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt src/main/kotlin/org/openapitools/client/infrastructure/Errors.kt src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt @@ -23,6 +26,8 @@ src/main/kotlin/org/openapitools/client/infrastructure/RequestConfig.kt src/main/kotlin/org/openapitools/client/infrastructure/RequestMethod.kt src/main/kotlin/org/openapitools/client/infrastructure/ResponseExtensions.kt src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt +src/main/kotlin/org/openapitools/client/infrastructure/StringBuilderAdapter.kt src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/URLAdapter.kt src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt src/main/kotlin/org/openapitools/client/models/PetEnum.kt diff --git a/samples/client/petstore/kotlin-uppercase-enum/build.gradle b/samples/client/petstore/kotlin-uppercase-enum/build.gradle index 3de8b45b135..41109c8e010 100644 --- a/samples/client/petstore/kotlin-uppercase-enum/build.gradle +++ b/samples/client/petstore/kotlin-uppercase-enum/build.gradle @@ -14,10 +14,12 @@ buildscript { } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" } } apply plugin: 'kotlin' +apply plugin: 'kotlinx-serialization' repositories { maven { url "https://repo1.maven.org/maven2" } @@ -29,9 +31,13 @@ test { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" - implementation "com.squareup.moshi:moshi-kotlin:1.12.0" - implementation "com.squareup.moshi:moshi-adapters:1.12.0" + implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.1" implementation "com.squareup.okhttp3:okhttp:4.9.1" testImplementation "io.kotlintest:kotlintest-runner-junit5:3.4.2" } + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { + kotlinOptions { + freeCompilerArgs += "-Xopt-in=kotlinx.serialization.ExperimentalSerializationApi" + } +} diff --git a/samples/client/petstore/kotlin-uppercase-enum/docs/PetEnum.md b/samples/client/petstore/kotlin-uppercase-enum/docs/PetEnum.md index d970c3dd862..cab9c95f783 100644 --- a/samples/client/petstore/kotlin-uppercase-enum/docs/PetEnum.md +++ b/samples/client/petstore/kotlin-uppercase-enum/docs/PetEnum.md @@ -8,5 +8,7 @@ * `MY_SECOND_VALUE` (value: `"MY_SECOND_VALUE"`) + * `UNKNOWN_DEFAULT_OPEN_API` (value: `"unknown_default_open_api"`) + diff --git a/samples/client/petstore/kotlin-uppercase-enum/proguard-rules.pro b/samples/client/petstore/kotlin-uppercase-enum/proguard-rules.pro new file mode 100644 index 00000000000..7c7b08bf381 --- /dev/null +++ b/samples/client/petstore/kotlin-uppercase-enum/proguard-rules.pro @@ -0,0 +1,11 @@ +-keepattributes *Annotation*, InnerClasses +-dontnote kotlinx.serialization.AnnotationsKt # core serialization annotations + +# kotlinx-serialization-json specific. Add this if you have java.lang.NoClassDefFoundError kotlinx.serialization.json.JsonObjectSerializer +-keepclassmembers class kotlinx.serialization.json.** { *** Companion; } +-keepclasseswithmembers class kotlinx.serialization.json.** { kotlinx.serialization.KSerializer serializer(...); } + +# project specific. +-keep,includedescriptorclasses class org.openapitools.client.models.**$$serializer { *; } +-keepclassmembers class org.openapitools.client.models.** { *** Companion; } +-keepclasseswithmembers class org.openapitools.client.models.** { kotlinx.serialization.KSerializer serializer(...); } diff --git a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/apis/EnumApi.kt b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/apis/EnumApi.kt index 7f1765943b3..56c1dfb819b 100644 --- a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/apis/EnumApi.kt +++ b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/apis/EnumApi.kt @@ -25,7 +25,8 @@ import okhttp3.OkHttpClient import org.openapitools.client.models.PetEnum -import com.squareup.moshi.Json +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable import org.openapitools.client.infrastructure.ApiClient import org.openapitools.client.infrastructure.ApiResponse diff --git a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index bfd00ac6a2e..3d056f549d6 100644 --- a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -27,7 +27,8 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale -import com.squareup.moshi.adapter +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.encodeToString open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -104,7 +105,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie if (content == null) { EMPTY_REQUEST } else { - Serializer.moshi.adapter(T::class.java).toJson(content) + Serializer.kotlinxSerializationJson.encodeToString(content) .toRequestBody((mediaType ?: JsonMediaType).toMediaTypeOrNull()) } mediaType == XmlMediaType -> throw UnsupportedOperationException("xml not currently supported.") @@ -112,7 +113,6 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie else -> throw UnsupportedOperationException("requestBody currently only supports JSON body and File body.") } - @OptIn(ExperimentalStdlibApi::class) protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { if(body == null) { return null @@ -135,7 +135,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie } return when { mediaType==null || (mediaType.startsWith("application/") && mediaType.endsWith("json")) -> - Serializer.moshi.adapter().fromJson(bodyContent) + Serializer.kotlinxSerializationJson.decodeFromString(bodyContent) else -> throw UnsupportedOperationException("responseBody currently only supports JSON body.") } } @@ -237,6 +237,6 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie formatter. It also easily allows to provide a simple way to define a custom date format pattern inside a gson/moshi adapter. */ - return Serializer.moshi.adapter(T::class.java).toJson(value).replace("\"", "") + return Serializer.kotlinxSerializationJson.encodeToString(value).replace("\"", "") } } diff --git a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/AtomicBooleanAdapter.kt b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/AtomicBooleanAdapter.kt new file mode 100644 index 00000000000..80611e349b1 --- /dev/null +++ b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/AtomicBooleanAdapter.kt @@ -0,0 +1,21 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.util.concurrent.atomic.AtomicBoolean + +@Serializer(forClass = AtomicBoolean::class) +object AtomicBooleanAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: AtomicBoolean) { + encoder.encodeBoolean(value.get()) + } + + override fun deserialize(decoder: Decoder): AtomicBoolean = AtomicBoolean(decoder.decodeBoolean()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("AtomicBoolean", PrimitiveKind.BOOLEAN) +} diff --git a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/AtomicIntegerAdapter.kt b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/AtomicIntegerAdapter.kt new file mode 100644 index 00000000000..8a5a8bafc78 --- /dev/null +++ b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/AtomicIntegerAdapter.kt @@ -0,0 +1,21 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.util.concurrent.atomic.AtomicInteger + +@Serializer(forClass = AtomicInteger::class) +object AtomicIntegerAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: AtomicInteger) { + encoder.encodeInt(value.get()) + } + + override fun deserialize(decoder: Decoder): AtomicInteger = AtomicInteger(decoder.decodeInt()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("AtomicInteger", PrimitiveKind.INT) +} diff --git a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/AtomicLongAdapter.kt b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/AtomicLongAdapter.kt new file mode 100644 index 00000000000..5842c490889 --- /dev/null +++ b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/AtomicLongAdapter.kt @@ -0,0 +1,21 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.util.concurrent.atomic.AtomicLong + +@Serializer(forClass = AtomicLong::class) +object AtomicLongAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: AtomicLong) { + encoder.encodeLong(value.get()) + } + + override fun deserialize(decoder: Decoder): AtomicLong = AtomicLong(decoder.decodeLong()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("AtomicLong", PrimitiveKind.LONG) +} diff --git a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt index 064b57fc6b8..94cbcb573ae 100644 --- a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt +++ b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt @@ -1,17 +1,17 @@ package org.openapitools.client.infrastructure -import com.squareup.moshi.FromJson -import com.squareup.moshi.ToJson +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor import java.math.BigDecimal -class BigDecimalAdapter { - @ToJson - fun toJson(value: BigDecimal): String { - return value.toPlainString() - } - - @FromJson - fun fromJson(value: String): BigDecimal { - return BigDecimal(value) - } +@Serializer(forClass = BigDecimal::class) +object BigDecimalAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("BigDecimal", PrimitiveKind.STRING) + override fun deserialize(decoder: Decoder): BigDecimal = BigDecimal(decoder.decodeString()) + override fun serialize(encoder: Encoder, value: BigDecimal) = encoder.encodeString(value.toPlainString()) } diff --git a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt index 7df6057b450..8f0544aa2b8 100644 --- a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt +++ b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt @@ -1,17 +1,22 @@ package org.openapitools.client.infrastructure -import com.squareup.moshi.FromJson -import com.squareup.moshi.ToJson +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor import java.math.BigInteger -class BigIntegerAdapter { - @ToJson - fun toJson(value: BigInteger): String { - return value.toString() +@Serializer(forClass = BigInteger::class) +object BigIntegerAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("BigInteger", PrimitiveKind.STRING) + override fun deserialize(decoder: Decoder): BigInteger { + return BigInteger(decoder.decodeString()) } - @FromJson - fun fromJson(value: String): BigInteger { - return BigInteger(value) + override fun serialize(encoder: Encoder, value: BigInteger) { + encoder.encodeString(value.toString()) } } diff --git a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt deleted file mode 100644 index ff5e2a81ee8..00000000000 --- a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt +++ /dev/null @@ -1,12 +0,0 @@ -package org.openapitools.client.infrastructure - -import com.squareup.moshi.FromJson -import com.squareup.moshi.ToJson - -class ByteArrayAdapter { - @ToJson - fun toJson(data: ByteArray): String = String(data) - - @FromJson - fun fromJson(data: String): ByteArray = data.toByteArray() -} diff --git a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt index b2e1654479a..f7c632d6964 100644 --- a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt +++ b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt @@ -1,19 +1,24 @@ package org.openapitools.client.infrastructure -import com.squareup.moshi.FromJson -import com.squareup.moshi.ToJson +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor import java.time.LocalDate import java.time.format.DateTimeFormatter -class LocalDateAdapter { - @ToJson - fun toJson(value: LocalDate): String { - return DateTimeFormatter.ISO_LOCAL_DATE.format(value) +@Serializer(forClass = LocalDate::class) +object LocalDateAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocalDate", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: LocalDate) { + encoder.encodeString(DateTimeFormatter.ISO_LOCAL_DATE.format(value)) } - @FromJson - fun fromJson(value: String): LocalDate { - return LocalDate.parse(value, DateTimeFormatter.ISO_LOCAL_DATE) + override fun deserialize(decoder: Decoder): LocalDate { + return LocalDate.parse(decoder.decodeString(), DateTimeFormatter.ISO_LOCAL_DATE) } - } diff --git a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt index e082db94811..88bd1401139 100644 --- a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt +++ b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt @@ -1,19 +1,24 @@ package org.openapitools.client.infrastructure -import com.squareup.moshi.FromJson -import com.squareup.moshi.ToJson +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor import java.time.LocalDateTime import java.time.format.DateTimeFormatter -class LocalDateTimeAdapter { - @ToJson - fun toJson(value: LocalDateTime): String { - return DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(value) +@Serializer(forClass = LocalDateTime::class) +object LocalDateTimeAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: LocalDateTime) { + encoder.encodeString(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(value)) } - @FromJson - fun fromJson(value: String): LocalDateTime { - return LocalDateTime.parse(value, DateTimeFormatter.ISO_LOCAL_DATE_TIME) + override fun deserialize(decoder: Decoder): LocalDateTime { + return LocalDateTime.parse(decoder.decodeString(), DateTimeFormatter.ISO_LOCAL_DATE_TIME) } - } diff --git a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt index 87437871a31..e0fe9e3b532 100644 --- a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt +++ b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt @@ -1,19 +1,24 @@ package org.openapitools.client.infrastructure -import com.squareup.moshi.FromJson -import com.squareup.moshi.ToJson +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor import java.time.OffsetDateTime import java.time.format.DateTimeFormatter -class OffsetDateTimeAdapter { - @ToJson - fun toJson(value: OffsetDateTime): String { - return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(value) +@Serializer(forClass = OffsetDateTime::class) +object OffsetDateTimeAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("OffsetDateTime", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: OffsetDateTime) { + encoder.encodeString(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(value)) } - @FromJson - fun fromJson(value: String): OffsetDateTime { - return OffsetDateTime.parse(value, DateTimeFormatter.ISO_OFFSET_DATE_TIME) + override fun deserialize(decoder: Decoder): OffsetDateTime { + return OffsetDateTime.parse(decoder.decodeString(), DateTimeFormatter.ISO_OFFSET_DATE_TIME) } - } diff --git a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt index e22592e47d7..82473d228a0 100644 --- a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt +++ b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt @@ -1,23 +1,52 @@ package org.openapitools.client.infrastructure -import com.squareup.moshi.Moshi -import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory +import java.math.BigDecimal +import java.math.BigInteger +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.OffsetDateTime +import java.util.UUID +import kotlinx.serialization.json.Json +import kotlinx.serialization.modules.SerializersModule +import java.net.URI +import java.net.URL +import java.util.concurrent.atomic.AtomicBoolean +import java.util.concurrent.atomic.AtomicInteger +import java.util.concurrent.atomic.AtomicLong object Serializer { + @Deprecated("Use Serializer.kotlinxSerializationAdapters instead", replaceWith = ReplaceWith("Serializer.kotlinxSerializationAdapters")) @JvmStatic - val moshiBuilder: Moshi.Builder = Moshi.Builder() - .add(OffsetDateTimeAdapter()) - .add(LocalDateTimeAdapter()) - .add(LocalDateAdapter()) - .add(UUIDAdapter()) - .add(ByteArrayAdapter()) - .add(URIAdapter()) - .add(KotlinJsonAdapterFactory()) - .add(BigDecimalAdapter()) - .add(BigIntegerAdapter()) + val kotlinSerializationAdapters: SerializersModule + get() { return kotlinxSerializationAdapters } @JvmStatic - val moshi: Moshi by lazy { - moshiBuilder.build() + val kotlinxSerializationAdapters = SerializersModule { + contextual(BigDecimal::class, BigDecimalAdapter) + contextual(BigInteger::class, BigIntegerAdapter) + contextual(LocalDate::class, LocalDateAdapter) + contextual(LocalDateTime::class, LocalDateTimeAdapter) + contextual(OffsetDateTime::class, OffsetDateTimeAdapter) + contextual(UUID::class, UUIDAdapter) + contextual(AtomicInteger::class, AtomicIntegerAdapter) + contextual(AtomicLong::class, AtomicLongAdapter) + contextual(AtomicBoolean::class, AtomicBooleanAdapter) + contextual(URI::class, URIAdapter) + contextual(URL::class, URLAdapter) + contextual(StringBuilder::class, StringBuilderAdapter) + } + + @Deprecated("Use Serializer.kotlinxSerializationJson instead", replaceWith = ReplaceWith("Serializer.kotlinxSerializationJson")) + @JvmStatic + val jvmJson: Json + get() { return kotlinxSerializationJson } + + @JvmStatic + val kotlinxSerializationJson: Json by lazy { + Json { + serializersModule = kotlinxSerializationAdapters + ignoreUnknownKeys = true + isLenient = true + } } } diff --git a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/StringBuilderAdapter.kt b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/StringBuilderAdapter.kt new file mode 100644 index 00000000000..7a15749f062 --- /dev/null +++ b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/StringBuilderAdapter.kt @@ -0,0 +1,20 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor + +@Serializer(forClass = StringBuilder::class) +object StringBuilderAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: StringBuilder) { + encoder.encodeString(value.toString()) + } + + override fun deserialize(decoder: Decoder): StringBuilder = StringBuilder(decoder.decodeString()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("StringBuilder", PrimitiveKind.STRING) +} diff --git a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt index 927522757da..0856c99813c 100644 --- a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt +++ b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt @@ -1,13 +1,21 @@ package org.openapitools.client.infrastructure -import com.squareup.moshi.FromJson -import com.squareup.moshi.ToJson +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor import java.net.URI -class URIAdapter { - @ToJson - fun toJson(uri: URI) = uri.toString() +@Serializer(forClass = URI::class) +object URIAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: URI) { + encoder.encodeString(value.toASCIIString()) + } - @FromJson - fun fromJson(s: String): URI = URI.create(s) + override fun deserialize(decoder: Decoder): URI = URI(decoder.decodeString()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("URI", PrimitiveKind.STRING) } diff --git a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/URLAdapter.kt b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/URLAdapter.kt new file mode 100644 index 00000000000..0dead7a73f8 --- /dev/null +++ b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/URLAdapter.kt @@ -0,0 +1,21 @@ +package org.openapitools.client.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.net.URL + +@Serializer(forClass = URL::class) +object URLAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: URL) { + encoder.encodeString(value.toExternalForm()) + } + + override fun deserialize(decoder: Decoder): URL = URL(decoder.decodeString()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("URL", PrimitiveKind.STRING) +} diff --git a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt index 7ccf7dc25d2..fbae87c1a6c 100644 --- a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt +++ b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt @@ -1,13 +1,23 @@ package org.openapitools.client.infrastructure -import com.squareup.moshi.FromJson -import com.squareup.moshi.ToJson +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor import java.util.UUID -class UUIDAdapter { - @ToJson - fun toJson(uuid: UUID) = uuid.toString() +@Serializer(forClass = UUID::class) +object UUIDAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("UUID", PrimitiveKind.STRING) - @FromJson - fun fromJson(s: String): UUID = UUID.fromString(s) + override fun serialize(encoder: Encoder, value: UUID) { + encoder.encodeString(value.toString()) + } + + override fun deserialize(decoder: Decoder): UUID { + return UUID.fromString(decoder.decodeString()) + } } diff --git a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/models/PetEnum.kt b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/models/PetEnum.kt index 4d9fa1abd64..592fbf89c0b 100644 --- a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/models/PetEnum.kt +++ b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/models/PetEnum.kt @@ -21,21 +21,30 @@ package org.openapitools.client.models -import com.squareup.moshi.Json +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder /** * An enum with complex-ish naming * - * Values: MY_FIRST_VALUE,MY_SECOND_VALUE + * Values: MY_FIRST_VALUE,MY_SECOND_VALUE,UNKNOWN_DEFAULT_OPEN_API */ - +@Serializable(with = PetEnumSerializer::class) enum class PetEnum(val value: kotlin.String) { - @Json(name = "myFirstValue") + @SerialName(value = "myFirstValue") MY_FIRST_VALUE("myFirstValue"), - @Json(name = "MY_SECOND_VALUE") - MY_SECOND_VALUE("MY_SECOND_VALUE"); + @SerialName(value = "MY_SECOND_VALUE") + MY_SECOND_VALUE("MY_SECOND_VALUE"), + + @SerialName(value = "unknown_default_open_api") + UNKNOWN_DEFAULT_OPEN_API("unknown_default_open_api"); /** * Override toString() to avoid using the enum variable name as the value, and instead use @@ -64,3 +73,18 @@ enum class PetEnum(val value: kotlin.String) { } } +@Serializer(forClass = PetEnum::class) +internal object PetEnumSerializer : KSerializer { + override val descriptor = kotlin.String.serializer().descriptor + + override fun deserialize(decoder: Decoder): PetEnum { + val value = decoder.decodeSerializableValue(kotlin.String.serializer()) + return PetEnum.values().firstOrNull { it.value == value } + ?: PetEnum.UNKNOWN_DEFAULT_OPEN_API + } + + override fun serialize(encoder: Encoder, value: PetEnum) { + encoder.encodeSerializableValue(kotlin.String.serializer(), value.value) + } +} +