Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions core/api/kotlinx-serialization-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Original file line number Diff line number Diff line change
@@ -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())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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"}"""
// )
// }
}