diff options
author | Sergey Shanshin <sergey.shanshin@jetbrains.com> | 2022-06-16 14:27:03 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-16 14:27:03 +0300 |
commit | 4b6410019b03c0f816ea75cd8f3ee6b25341e2d9 (patch) | |
tree | c96845e351eb5473d14edce0f4881ae4f4c64ffe | |
parent | 74072c5d4fa72aa253962af72fe16a7ac2c755e6 (diff) | |
download | kotlinx.serialization-4b6410019b03c0f816ea75cd8f3ee6b25341e2d9.tar.gz |
Added support for the `kotlin.time.Duration` class as built-in
7 files changed, 104 insertions, 2 deletions
diff --git a/core/api/kotlinx-serialization-core.api b/core/api/kotlinx-serialization-core.api index 4ec311ba..8d5e9a7f 100644 --- a/core/api/kotlinx-serialization-core.api +++ b/core/api/kotlinx-serialization-core.api @@ -175,6 +175,7 @@ public final class kotlinx/serialization/builtins/BuiltinSerializersKt { public static final fun serializer (Lkotlin/jvm/internal/LongCompanionObject;)Lkotlinx/serialization/KSerializer; public static final fun serializer (Lkotlin/jvm/internal/ShortCompanionObject;)Lkotlinx/serialization/KSerializer; public static final fun serializer (Lkotlin/jvm/internal/StringCompanionObject;)Lkotlinx/serialization/KSerializer; + public static final fun serializer (Lkotlin/time/Duration$Companion;)Lkotlinx/serialization/KSerializer; } public final class kotlinx/serialization/builtins/LongAsStringSerializer : kotlinx/serialization/KSerializer { @@ -662,6 +663,15 @@ public final class kotlinx/serialization/internal/DoubleSerializer : kotlinx/ser public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V } +public final class kotlinx/serialization/internal/DurationSerializer : kotlinx/serialization/KSerializer { + public static final field INSTANCE Lkotlinx/serialization/internal/DurationSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize-5sfh64U (Lkotlinx/serialization/encoding/Decoder;)J + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize-HG0u8IE (Lkotlinx/serialization/encoding/Encoder;J)V +} + public final class kotlinx/serialization/internal/ElementMarker { public fun <init> (Lkotlinx/serialization/descriptors/SerialDescriptor;Lkotlin/jvm/functions/Function2;)V public final fun mark (I)V diff --git a/core/commonMain/src/kotlinx/serialization/builtins/BuiltinSerializers.kt b/core/commonMain/src/kotlinx/serialization/builtins/BuiltinSerializers.kt index 147f25d9..ddc42783 100644 --- a/core/commonMain/src/kotlinx/serialization/builtins/BuiltinSerializers.kt +++ b/core/commonMain/src/kotlinx/serialization/builtins/BuiltinSerializers.kt @@ -9,6 +9,7 @@ import kotlinx.serialization.* import kotlinx.serialization.internal.* import kotlin.reflect.* import kotlinx.serialization.descriptors.* +import kotlin.time.Duration /** * Returns a nullable serializer for the given serializer of non-null type. @@ -217,3 +218,11 @@ public fun UByte.Companion.serializer(): KSerializer<UByte> = UByteSerializer @ExperimentalSerializationApi @ExperimentalUnsignedTypes public fun UShort.Companion.serializer(): KSerializer<UShort> = UShortSerializer + +/** + * Returns serializer for [Duration]. + * It is serialized as a string that represents a duration in the ISO-8601 format. + * + * The result of serialization is similar to calling [Duration.toIsoString], for deserialization is [Duration.parseIsoString]. + */ +public fun Duration.Companion.serializer(): KSerializer<Duration> = DurationSerializer diff --git a/core/commonMain/src/kotlinx/serialization/internal/BuiltInSerializers.kt b/core/commonMain/src/kotlinx/serialization/internal/BuiltInSerializers.kt new file mode 100644 index 00000000..13735ee7 --- /dev/null +++ b/core/commonMain/src/kotlinx/serialization/internal/BuiltInSerializers.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ +package kotlinx.serialization.internal + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlin.time.Duration + + +@PublishedApi +internal object DurationSerializer : KSerializer<Duration> { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("kotlin.time.Duration", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: Duration) { + encoder.encodeString(value.toIsoString()) + } + + override fun deserialize(decoder: Decoder): Duration { + return Duration.parseIsoString(decoder.decodeString()) + } +} diff --git a/core/commonMain/src/kotlinx/serialization/internal/Primitives.kt b/core/commonMain/src/kotlinx/serialization/internal/Primitives.kt index ab127ffa..dfc9aafa 100644 --- a/core/commonMain/src/kotlinx/serialization/internal/Primitives.kt +++ b/core/commonMain/src/kotlinx/serialization/internal/Primitives.kt @@ -13,6 +13,7 @@ import kotlinx.serialization.descriptors.* import kotlinx.serialization.encoding.* import kotlin.native.concurrent.* import kotlin.reflect.* +import kotlin.time.Duration @SharedImmutable private val BUILTIN_SERIALIZERS = mapOf( @@ -33,7 +34,8 @@ private val BUILTIN_SERIALIZERS = mapOf( ByteArray::class to ByteArraySerializer(), Boolean::class to Boolean.serializer(), BooleanArray::class to BooleanArraySerializer(), - Unit::class to Unit.serializer() + Unit::class to Unit.serializer(), + Duration::class to Duration.serializer() ) internal class PrimitiveSerialDescriptor( diff --git a/core/commonTest/src/kotlinx/serialization/BasicTypesSerializationTest.kt b/core/commonTest/src/kotlinx/serialization/BasicTypesSerializationTest.kt index 82cbb2ae..dc443fd2 100644 --- a/core/commonTest/src/kotlinx/serialization/BasicTypesSerializationTest.kt +++ b/core/commonTest/src/kotlinx/serialization/BasicTypesSerializationTest.kt @@ -4,12 +4,13 @@ package kotlinx.serialization +import kotlinx.serialization.builtins.serializer import kotlinx.serialization.descriptors.* import kotlinx.serialization.encoding.* import kotlinx.serialization.encoding.CompositeDecoder.Companion.UNKNOWN_NAME -import kotlinx.serialization.internal.* import kotlinx.serialization.modules.* import kotlin.test.* +import kotlin.time.Duration /* * Test ensures that type that aggregate all basic (primitive/collection/maps/arrays) @@ -170,4 +171,24 @@ class BasicTypesSerializationTest { assertEquals(umbrellaInstance, other) assertNotSame(umbrellaInstance, other) } + + @Test + fun testEncodeDuration() { + val sb = StringBuilder() + val out = KeyValueOutput(sb) + + val duration = Duration.parseIsoString("P4DT12H30M5S") + out.encodeSerializableValue(Duration.serializer(), duration) + + assertEquals("\"${duration.toIsoString()}\"", sb.toString()) + } + + @Test + fun testDecodeDuration() { + val durationString = "P4DT12H30M5S" + val inp = KeyValueInput(Parser(StringReader("\"$durationString\""))) + val other = inp.decodeSerializableValue(Duration.serializer()) + assertEquals(Duration.parseIsoString(durationString), other) + } + } diff --git a/formats/json/commonTest/src/kotlinx/serialization/SerializersLookupTest.kt b/formats/json/commonTest/src/kotlinx/serialization/SerializersLookupTest.kt index 18a69404..c5dcf201 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/SerializersLookupTest.kt +++ b/formats/json/commonTest/src/kotlinx/serialization/SerializersLookupTest.kt @@ -14,6 +14,7 @@ import kotlinx.serialization.modules.* import kotlinx.serialization.test.* import kotlin.reflect.* import kotlin.test.* +import kotlin.time.Duration @Suppress("RemoveExplicitTypeArguments") // This is exactly what's being tested class SerializersLookupTest : JsonTestBase() { @@ -243,6 +244,13 @@ class SerializersLookupTest : JsonTestBase() { } } +// TODO uncomment when Kotlin 1.7.20 is released +// @Test +// fun testLookupDuration() = noLegacyJs { +// assertNotNull(serializerOrNull(typeOf<Duration>())) +// assertSame(Duration.serializer(), serializer<Duration>()) +// } + private inline fun <reified T> assertSerializedWithType( expected: String, value: T, diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/DurationTest.kt b/formats/json/commonTest/src/kotlinx/serialization/features/DurationTest.kt new file mode 100644 index 00000000..a94ae43f --- /dev/null +++ b/formats/json/commonTest/src/kotlinx/serialization/features/DurationTest.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.features + +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonTestBase +import kotlin.test.Test +import kotlin.time.Duration +import kotlin.time.DurationUnit +import kotlin.time.toDuration + + +class DurationTest : JsonTestBase() { +// TODO uncomment when Kotlin 1.7.20 is released +// @Serializable +// data class DurationHolder(val duration: Duration) +// @Test +// fun testDuration() { +// assertJsonFormAndRestored( +// DurationHolder.serializer(), +// DurationHolder(1000.toDuration(DurationUnit.SECONDS)), +// """{"duration":"PT16M40S"}""" +// ) +// } +} |