Skip to content

Commit d9753af

Browse files
authored
Check against serialName instead of simpleClassName (#2802)
in PrimitiveSerialDescriptor constructor. By doing so, we allow users to declare their own serializers with short names like "Uuid" or "Duration", even though it is not recommended — because they may have been declared before library updates. Fixes #2799
1 parent 0b015e1 commit d9753af

File tree

3 files changed

+64
-8
lines changed

3 files changed

+64
-8
lines changed

core/commonMain/src/kotlinx/serialization/internal/Primitives.kt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,13 @@ internal fun PrimitiveDescriptorSafe(serialName: String, kind: PrimitiveKind): S
4646
}
4747

4848
private fun checkName(serialName: String) {
49-
val keys = BUILTIN_SERIALIZERS.keys
50-
for (primitive in keys) {
51-
val simpleName = primitive.simpleName!!.capitalize()
52-
val qualifiedName = "kotlin.$simpleName" // KClass.qualifiedName is not supported in JS
53-
if (serialName.equals(qualifiedName, ignoreCase = true) || serialName.equals(simpleName, ignoreCase = true)) {
49+
val values = BUILTIN_SERIALIZERS.values
50+
for (primitive in values) {
51+
val primitiveName = primitive.descriptor.serialName
52+
if (serialName == primitiveName) {
5453
throw IllegalArgumentException("""
5554
The name of serial descriptor should uniquely identify associated serializer.
56-
For serial name $serialName there already exist ${simpleName.capitalize()}Serializer.
55+
For serial name $serialName there already exists ${primitive::class.simpleName}.
5756
Please refer to SerialDescriptor documentation for additional information.
5857
""".trimIndent())
5958
}

core/commonTest/src/kotlinx/serialization/SerialDescriptorSpecificationTest.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,9 +204,10 @@ class SerialDescriptorSpecificationTest {
204204

205205
@Test
206206
fun testCustomPrimitiveDescriptor() {
207+
// It is allowed to have a custom descriptor with 'Int' or 'int', but not 'kotlin.Int'.
207208
assertFailsWith<IllegalArgumentException> { PrimitiveSerialDescriptor("kotlin.Int", PrimitiveKind.INT) }
208-
assertFailsWith<IllegalArgumentException> { PrimitiveSerialDescriptor("Int", PrimitiveKind.INT) }
209-
assertFailsWith<IllegalArgumentException> { PrimitiveSerialDescriptor("int", PrimitiveKind.INT) }
209+
assertEquals("Int", PrimitiveSerialDescriptor("Int", PrimitiveKind.INT).serialName)
210+
assertEquals("int", PrimitiveSerialDescriptor("int", PrimitiveKind.INT).serialName)
210211
}
211212

212213
private fun checkPrimitiveDescriptor(type: String, descriptor: SerialDescriptor) {
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2017-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package kotlinx.serialization
6+
7+
import kotlinx.serialization.builtins.*
8+
import kotlinx.serialization.descriptors.*
9+
import kotlinx.serialization.encoding.*
10+
import kotlinx.serialization.json.*
11+
import kotlinx.serialization.modules.*
12+
import kotlin.test.*
13+
import kotlin.uuid.*
14+
import java.util.UUID as JUuid
15+
import kotlin.uuid.Uuid as KUuid
16+
17+
@OptIn(ExperimentalUuidApi::class)
18+
class UuidPlatformClashTest : JsonTestBase() {
19+
object JavaUuidSerializer : KSerializer<JUuid> {
20+
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Uuid", PrimitiveKind.STRING)
21+
22+
override fun serialize(encoder: Encoder, value: JUuid) {
23+
encoder.encodeString(value.toString().uppercase())
24+
}
25+
26+
override fun deserialize(decoder: Decoder): JUuid {
27+
return JUuid.fromString(decoder.decodeString())
28+
}
29+
}
30+
31+
32+
@Serializable
33+
data class UuidPair(
34+
@Contextual val jUuid: JUuid,
35+
@Contextual val kUuid: KUuid,
36+
)
37+
38+
@Test
39+
fun testUuids() {
40+
val module = SerializersModule {
41+
contextual(JavaUuidSerializer)
42+
contextual(KUuid.serializer())
43+
}
44+
val json = Json { serializersModule = module }
45+
val pair = UuidPair(
46+
JUuid.fromString("252660b8-9a2b-44d1-a804-9a23f881cec5"),
47+
KUuid.parse("c8ad1526-4b7c-4b67-9f77-6d05e580ad71")
48+
)
49+
assertJsonFormAndRestored(
50+
UuidPair.serializer(),
51+
pair,
52+
"""{"jUuid":"252660B8-9A2B-44D1-A804-9A23F881CEC5","kUuid":"c8ad1526-4b7c-4b67-9f77-6d05e580ad71"}""",
53+
json
54+
)
55+
}
56+
}

0 commit comments

Comments
 (0)