From f678d425a4fc4abd7509b49d453c34028bdc6f84 Mon Sep 17 00:00:00 2001 From: Dmitry Khalanskiy Date: Thu, 25 Jul 2024 15:40:08 +0200 Subject: [PATCH] Ensure different serial names for incompatible serializers Fixes #416 --- core/common/src/DateTimePeriod.kt | 9 ++++++--- .../serializers/DateTimePeriodSerializers.kt | 20 +++++++++++++++---- .../src/serializers/InstantSerializers.kt | 4 ++-- .../src/serializers/LocalDateSerializers.kt | 4 ++-- .../serializers/LocalDateTimeSerializers.kt | 4 ++-- .../src/serializers/LocalTimeSerializers.kt | 4 ++-- .../src/serializers/TimeZoneSerializers.kt | 2 +- .../test/DateTimePeriodSerializationTest.kt | 8 ++++---- .../common/test/InstantSerializationTest.kt | 4 ++-- .../common/test/LocalDateSerializationTest.kt | 4 ++-- .../test/LocalDateTimeSerializationTest.kt | 6 ++++-- .../common/test/LocalTimeSerializationTest.kt | 4 ++-- .../common/test/UtcOffsetSerializationTest.kt | 2 +- 13 files changed, 46 insertions(+), 29 deletions(-) diff --git a/core/common/src/DateTimePeriod.kt b/core/common/src/DateTimePeriod.kt index f9b2d3f3..5b5141d5 100644 --- a/core/common/src/DateTimePeriod.kt +++ b/core/common/src/DateTimePeriod.kt @@ -9,7 +9,9 @@ import kotlinx.datetime.internal.* import kotlinx.datetime.serializers.DatePeriodIso8601Serializer import kotlinx.datetime.serializers.DateTimePeriodIso8601Serializer import kotlinx.datetime.serializers.DatePeriodComponentSerializer +import kotlinx.datetime.serializers.DatePeriodSerializer import kotlinx.datetime.serializers.DateTimePeriodComponentSerializer +import kotlinx.datetime.serializers.DateTimePeriodSerializer import kotlin.math.* import kotlin.time.Duration import kotlinx.serialization.Serializable @@ -63,13 +65,14 @@ import kotlinx.serialization.Serializable * `DateTimePeriod` can also be returned as the result of instant arithmetic operations (see [Instant.periodUntil]). * * Additionally, there are several `kotlinx-serialization` serializers for [DateTimePeriod]: - * - [DateTimePeriodIso8601Serializer] for the ISO 8601 format; + * - The default serializer, delegating to [toString] and [parse]. + * - [DateTimePeriodIso8601Serializer] for the ISO 8601 format. * - [DateTimePeriodComponentSerializer] for an object with components. * * @sample kotlinx.datetime.test.samples.DateTimePeriodSamples.construction * @sample kotlinx.datetime.test.samples.DateTimePeriodSamples.simpleParsingAndFormatting */ -@Serializable(with = DateTimePeriodIso8601Serializer::class) +@Serializable(with = DateTimePeriodSerializer::class) // TODO: could be error-prone without explicitly named params public sealed class DateTimePeriod { internal abstract val totalMonths: Int @@ -426,7 +429,7 @@ public fun String.toDateTimePeriod(): DateTimePeriod = DateTimePeriod.parse(this * * @sample kotlinx.datetime.test.samples.DatePeriodSamples.simpleParsingAndFormatting */ -@Serializable(with = DatePeriodIso8601Serializer::class) +@Serializable(with = DatePeriodSerializer::class) public class DatePeriod internal constructor( internal override val totalMonths: Int, override val days: Int, diff --git a/core/common/src/serializers/DateTimePeriodSerializers.kt b/core/common/src/serializers/DateTimePeriodSerializers.kt index e5d904fc..ac76db34 100644 --- a/core/common/src/serializers/DateTimePeriodSerializers.kt +++ b/core/common/src/serializers/DateTimePeriodSerializers.kt @@ -19,7 +19,7 @@ import kotlinx.serialization.encoding.* public object DateTimePeriodComponentSerializer: KSerializer { override val descriptor: SerialDescriptor = - buildClassSerialDescriptor("kotlinx.datetime.DateTimePeriod") { + buildClassSerialDescriptor("kotlinx.datetime.DateTimePeriod components") { element("years", isOptional = true) element("months", isOptional = true) element("days", isOptional = true) @@ -81,7 +81,7 @@ public object DateTimePeriodComponentSerializer: KSerializer { public object DateTimePeriodIso8601Serializer: KSerializer { override val descriptor: SerialDescriptor = - PrimitiveSerialDescriptor("kotlinx.datetime.DateTimePeriod", PrimitiveKind.STRING) + PrimitiveSerialDescriptor("kotlinx.datetime.DateTimePeriod ISO", PrimitiveKind.STRING) override fun deserialize(decoder: Decoder): DateTimePeriod = DateTimePeriod.parse(decoder.decodeString()) @@ -110,7 +110,7 @@ public object DatePeriodComponentSerializer: KSerializer { private fun unexpectedNonzero(fieldName: String, value: Int) = unexpectedNonzero(fieldName, value.toLong()) override val descriptor: SerialDescriptor = - buildClassSerialDescriptor("kotlinx.datetime.DatePeriod") { + buildClassSerialDescriptor("kotlinx.datetime.DatePeriod components") { element("years", isOptional = true) element("months", isOptional = true) element("days", isOptional = true) @@ -166,7 +166,7 @@ public object DatePeriodComponentSerializer: KSerializer { public object DatePeriodIso8601Serializer: KSerializer { override val descriptor: SerialDescriptor = - PrimitiveSerialDescriptor("kotlinx.datetime.DatePeriod", PrimitiveKind.STRING) + PrimitiveSerialDescriptor("kotlinx.datetime.DatePeriod ISO", PrimitiveKind.STRING) override fun deserialize(decoder: Decoder): DatePeriod = when (val period = DateTimePeriod.parse(decoder.decodeString())) { @@ -179,3 +179,15 @@ public object DatePeriodIso8601Serializer: KSerializer { } } + +@PublishedApi +internal object DateTimePeriodSerializer: KSerializer by DateTimePeriodIso8601Serializer { + override val descriptor = + PrimitiveSerialDescriptor("kotlinx.datetime.DateTimePeriod", PrimitiveKind.STRING) +} + +@PublishedApi +internal object DatePeriodSerializer: KSerializer by DatePeriodIso8601Serializer { + override val descriptor = + PrimitiveSerialDescriptor("kotlinx.datetime.DatePeriod", PrimitiveKind.STRING) +} diff --git a/core/common/src/serializers/InstantSerializers.kt b/core/common/src/serializers/InstantSerializers.kt index e46a0c44..1b3ccdd9 100644 --- a/core/common/src/serializers/InstantSerializers.kt +++ b/core/common/src/serializers/InstantSerializers.kt @@ -22,7 +22,7 @@ import kotlinx.serialization.encoding.* public object InstantIso8601Serializer : KSerializer { override val descriptor: SerialDescriptor = - PrimitiveSerialDescriptor("kotlinx.datetime.Instant", PrimitiveKind.STRING) + PrimitiveSerialDescriptor("kotlinx.datetime.Instant ISO", PrimitiveKind.STRING) override fun deserialize(decoder: Decoder): Instant = Instant.parse(decoder.decodeString(), DateTimeComponents.Formats.ISO_DATE_TIME_OFFSET) @@ -41,7 +41,7 @@ public object InstantIso8601Serializer : KSerializer { public object InstantComponentSerializer : KSerializer { override val descriptor: SerialDescriptor = - buildClassSerialDescriptor("kotlinx.datetime.Instant") { + buildClassSerialDescriptor("kotlinx.datetime.Instant components") { element("epochSeconds") element("nanosecondsOfSecond", isOptional = true) } diff --git a/core/common/src/serializers/LocalDateSerializers.kt b/core/common/src/serializers/LocalDateSerializers.kt index aaa0e2bf..b684b44f 100644 --- a/core/common/src/serializers/LocalDateSerializers.kt +++ b/core/common/src/serializers/LocalDateSerializers.kt @@ -19,7 +19,7 @@ import kotlinx.serialization.encoding.* * @see LocalDate.Formats.ISO */ public object LocalDateIso8601Serializer : KSerializer -by LocalDate.Formats.ISO.asKSerializer("kotlinx.datetime.LocalDate") +by LocalDate.Formats.ISO.asKSerializer("kotlinx.datetime.LocalDate ISO") /** * A serializer for [LocalDate] that represents a value as its components. @@ -29,7 +29,7 @@ by LocalDate.Formats.ISO.asKSerializer("kotlinx.datetime.LocalDate") public object LocalDateComponentSerializer: KSerializer { override val descriptor: SerialDescriptor = - buildClassSerialDescriptor("kotlinx.datetime.LocalDate") { + buildClassSerialDescriptor("kotlinx.datetime.LocalDate components") { element("year") element("month") element("day") diff --git a/core/common/src/serializers/LocalDateTimeSerializers.kt b/core/common/src/serializers/LocalDateTimeSerializers.kt index ddbe3838..40f60742 100644 --- a/core/common/src/serializers/LocalDateTimeSerializers.kt +++ b/core/common/src/serializers/LocalDateTimeSerializers.kt @@ -19,7 +19,7 @@ import kotlinx.serialization.encoding.* * @see LocalDateTime.Formats.ISO */ public object LocalDateTimeIso8601Serializer : KSerializer -by LocalDateTime.Formats.ISO.asKSerializer("kotlinx.datetime.LocalDateTime") +by LocalDateTime.Formats.ISO.asKSerializer("kotlinx.datetime.LocalDateTime ISO") /** * A serializer for [LocalDateTime] that represents a value as its components. @@ -29,7 +29,7 @@ by LocalDateTime.Formats.ISO.asKSerializer("kotlinx.datetime.LocalDateTime") public object LocalDateTimeComponentSerializer: KSerializer { override val descriptor: SerialDescriptor = - buildClassSerialDescriptor("kotlinx.datetime.LocalDateTime") { + buildClassSerialDescriptor("kotlinx.datetime.LocalDateTime components") { element("year") element("month") element("day") diff --git a/core/common/src/serializers/LocalTimeSerializers.kt b/core/common/src/serializers/LocalTimeSerializers.kt index 0b86050b..d67a6350 100644 --- a/core/common/src/serializers/LocalTimeSerializers.kt +++ b/core/common/src/serializers/LocalTimeSerializers.kt @@ -19,7 +19,7 @@ import kotlinx.serialization.encoding.* * @see LocalTime.Formats.ISO */ public object LocalTimeIso8601Serializer : KSerializer -by LocalTime.Formats.ISO.asKSerializer("kotlinx.datetime.LocalTime") +by LocalTime.Formats.ISO.asKSerializer("kotlinx.datetime.LocalTime ISO") /** * A serializer for [LocalTime] that represents a value as its components. @@ -29,7 +29,7 @@ by LocalTime.Formats.ISO.asKSerializer("kotlinx.datetime.LocalTime") public object LocalTimeComponentSerializer : KSerializer { override val descriptor: SerialDescriptor = - buildClassSerialDescriptor("kotlinx.datetime.LocalTime") { + buildClassSerialDescriptor("kotlinx.datetime.LocalTime components") { element("hour") element("minute") element("second", isOptional = true) diff --git a/core/common/src/serializers/TimeZoneSerializers.kt b/core/common/src/serializers/TimeZoneSerializers.kt index f9281809..538aee5b 100644 --- a/core/common/src/serializers/TimeZoneSerializers.kt +++ b/core/common/src/serializers/TimeZoneSerializers.kt @@ -60,7 +60,7 @@ public object FixedOffsetTimeZoneSerializer: KSerializer { * @see UtcOffset.Formats.ISO */ public object UtcOffsetIso8601Serializer : KSerializer -by UtcOffset.Formats.ISO.asKSerializer("kotlinx.datetime.UtcOffset") +by UtcOffset.Formats.ISO.asKSerializer("kotlinx.datetime.UtcOffset ISO") /** * A serializer for [UtcOffset] that uses the default [UtcOffset.toString]/[UtcOffset.parse]. diff --git a/serialization/common/test/DateTimePeriodSerializationTest.kt b/serialization/common/test/DateTimePeriodSerializationTest.kt index ddb2f606..9869d424 100644 --- a/serialization/common/test/DateTimePeriodSerializationTest.kt +++ b/serialization/common/test/DateTimePeriodSerializationTest.kt @@ -97,25 +97,25 @@ class DateTimePeriodSerializationTest { @Test fun testDatePeriodIso8601Serialization() { - assertKSerializerName("kotlinx.datetime.DatePeriod", DatePeriodIso8601Serializer) + assertKSerializerName("kotlinx.datetime.DatePeriod ISO", DatePeriodIso8601Serializer) datePeriodIso8601Serialization(DatePeriodIso8601Serializer, DateTimePeriodIso8601Serializer) } @Test fun testDatePeriodComponentSerialization() { - assertKSerializerName("kotlinx.datetime.DatePeriod", DatePeriodComponentSerializer) + assertKSerializerName("kotlinx.datetime.DatePeriod components", DatePeriodComponentSerializer) datePeriodComponentSerialization(DatePeriodComponentSerializer, DateTimePeriodComponentSerializer) } @Test fun testDateTimePeriodIso8601Serialization() { - assertKSerializerName("kotlinx.datetime.DateTimePeriod", DateTimePeriodIso8601Serializer) + assertKSerializerName("kotlinx.datetime.DateTimePeriod ISO", DateTimePeriodIso8601Serializer) dateTimePeriodIso8601Serialization(DateTimePeriodIso8601Serializer) } @Test fun testDateTimePeriodComponentSerialization() { - assertKSerializerName("kotlinx.datetime.DateTimePeriod", DateTimePeriodComponentSerializer) + assertKSerializerName("kotlinx.datetime.DateTimePeriod components", DateTimePeriodComponentSerializer) dateTimePeriodComponentSerialization(DateTimePeriodComponentSerializer) } diff --git a/serialization/common/test/InstantSerializationTest.kt b/serialization/common/test/InstantSerializationTest.kt index 6d83dc0b..d7a18a2b 100644 --- a/serialization/common/test/InstantSerializationTest.kt +++ b/serialization/common/test/InstantSerializationTest.kt @@ -70,13 +70,13 @@ class InstantSerializationTest { @Test fun testIso8601Serialization() { - assertKSerializerName("kotlinx.datetime.Instant", InstantIso8601Serializer) + assertKSerializerName("kotlinx.datetime.Instant ISO", InstantIso8601Serializer) iso8601Serialization(InstantIso8601Serializer) } @Test fun testComponentSerialization() { - assertKSerializerName("kotlinx.datetime.Instant", InstantComponentSerializer) + assertKSerializerName("kotlinx.datetime.Instant components", InstantComponentSerializer) componentSerialization(InstantComponentSerializer) } diff --git a/serialization/common/test/LocalDateSerializationTest.kt b/serialization/common/test/LocalDateSerializationTest.kt index bd6dd951..420c4db4 100644 --- a/serialization/common/test/LocalDateSerializationTest.kt +++ b/serialization/common/test/LocalDateSerializationTest.kt @@ -56,13 +56,13 @@ class LocalDateSerializationTest { @Test fun testIso8601Serialization() { - assertKSerializerName("kotlinx.datetime.LocalDate", LocalDateIso8601Serializer) + assertKSerializerName("kotlinx.datetime.LocalDate ISO", LocalDateIso8601Serializer) iso8601Serialization(LocalDateIso8601Serializer) } @Test fun testComponentSerialization() { - assertKSerializerName("kotlinx.datetime.LocalDate", LocalDateComponentSerializer) + assertKSerializerName("kotlinx.datetime.LocalDate components", LocalDateComponentSerializer) componentSerialization(LocalDateComponentSerializer) } diff --git a/serialization/common/test/LocalDateTimeSerializationTest.kt b/serialization/common/test/LocalDateTimeSerializationTest.kt index 63649a34..aede7abb 100644 --- a/serialization/common/test/LocalDateTimeSerializationTest.kt +++ b/serialization/common/test/LocalDateTimeSerializationTest.kt @@ -83,13 +83,15 @@ class LocalDateTimeSerializationTest { @Test fun testIso8601Serialization() { - assertKSerializerName("kotlinx.datetime.LocalDateTime", LocalDateTimeComponentSerializer) + assertKSerializerName("kotlinx.datetime.LocalDateTime ISO", LocalDateTimeIso8601Serializer) iso8601Serialization(LocalDateTimeIso8601Serializer) } @Test fun testComponentSerialization() { - assertKSerializerName("kotlinx.datetime.LocalDateTime", LocalDateTimeComponentSerializer) + assertKSerializerName( + "kotlinx.datetime.LocalDateTime components", LocalDateTimeComponentSerializer + ) componentSerialization(LocalDateTimeComponentSerializer) } diff --git a/serialization/common/test/LocalTimeSerializationTest.kt b/serialization/common/test/LocalTimeSerializationTest.kt index 3bd6e09c..c7d44b40 100644 --- a/serialization/common/test/LocalTimeSerializationTest.kt +++ b/serialization/common/test/LocalTimeSerializationTest.kt @@ -73,13 +73,13 @@ class LocalTimeSerializationTest { @Test fun testIso8601Serialization() { - assertKSerializerName("kotlinx.datetime.LocalTime", LocalTimeIso8601Serializer) + assertKSerializerName("kotlinx.datetime.LocalTime ISO", LocalTimeIso8601Serializer) iso8601Serialization(LocalTimeIso8601Serializer) } @Test fun testComponentSerialization() { - assertKSerializerName("kotlinx.datetime.LocalTime", LocalTimeComponentSerializer) + assertKSerializerName("kotlinx.datetime.LocalTime components", LocalTimeComponentSerializer) componentSerialization(LocalTimeComponentSerializer) } diff --git a/serialization/common/test/UtcOffsetSerializationTest.kt b/serialization/common/test/UtcOffsetSerializationTest.kt index 32304f13..b4ac0477 100644 --- a/serialization/common/test/UtcOffsetSerializationTest.kt +++ b/serialization/common/test/UtcOffsetSerializationTest.kt @@ -47,7 +47,7 @@ class UtcOffsetSerializationTest { @Test fun testIso8601Serialization() { - assertKSerializerName("kotlinx.datetime.UtcOffset", UtcOffsetIso8601Serializer) + assertKSerializerName("kotlinx.datetime.UtcOffset ISO", UtcOffsetIso8601Serializer) iso8601Serialization(UtcOffsetIso8601Serializer) }