Skip to content

Commit 881e7a9

Browse files
authored
Fixed regression with serialization using list parametrized with contextual types (#2331)
Fixes #2323 In the current implementation of serializer lookup caching, if the serializer for the parameter was not found, the `serializerOrNull` function always returned null, without further searching for contextual serializers in the current SerializersModule.
1 parent 780f43e commit 881e7a9

File tree

2 files changed

+39
-7
lines changed

2 files changed

+39
-7
lines changed

core/commonMain/src/kotlinx/serialization/Serializers.kt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -193,13 +193,7 @@ private fun SerializersModule.serializerByKTypeImpl(
193193
val cachedSerializer = if (typeArguments.isEmpty()) {
194194
findCachedSerializer(rootClass, isNullable)
195195
} else {
196-
val cachedResult = findParametrizedCachedSerializer(rootClass, typeArguments, isNullable)
197-
if (failOnMissingTypeArgSerializer) {
198-
cachedResult.getOrNull()
199-
} else {
200-
// return null if error occurred - serializer for parameter(s) was not found
201-
cachedResult.getOrElse { return null }
202-
}
196+
findParametrizedCachedSerializer(rootClass, typeArguments, isNullable).getOrNull()
203197
}
204198
cachedSerializer?.let { return it }
205199

formats/json-tests/commonTest/src/kotlinx/serialization/SerializersLookupTest.kt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class SerializersLookupTest : JsonTestBase() {
5959
assertSame(UInt.serializer(), serializer<UInt>())
6060
assertSame(ULong.serializer(), serializer<ULong>())
6161
}
62+
6263
@Test
6364
@OptIn(ExperimentalUnsignedTypes::class)
6465
fun testUnsignedArrays() {
@@ -210,6 +211,24 @@ class SerializersLookupTest : JsonTestBase() {
210211
}
211212
}
212213

214+
class GenericHolder<T>(value: T)
215+
216+
class GenericSerializer<T>(typeSerializer: KSerializer<T>) : KSerializer<GenericHolder<T>> {
217+
override val descriptor: SerialDescriptor =
218+
PrimitiveSerialDescriptor(
219+
"Generic Serializer parametrized by ${typeSerializer.descriptor}",
220+
PrimitiveKind.STRING
221+
)
222+
223+
override fun deserialize(decoder: Decoder): GenericHolder<T> {
224+
TODO()
225+
}
226+
227+
override fun serialize(encoder: Encoder, value: GenericHolder<T>) {
228+
TODO()
229+
}
230+
}
231+
213232
@Test
214233
fun testContextualLookup() {
215234
val module = SerializersModule { contextual(CustomIntSerializer(false).cast<IntBox>()) }
@@ -218,6 +237,25 @@ class SerializersLookupTest : JsonTestBase() {
218237
assertEquals("[[42]]", json.encodeToString(data))
219238
}
220239

240+
@Test
241+
fun testGenericOfContextual() {
242+
val module = SerializersModule {
243+
contextual(CustomIntSerializer(false).cast<IntBox>())
244+
contextual(GenericHolder::class) { args -> GenericSerializer(args[0]) }
245+
}
246+
247+
val listSerializer = module.serializerOrNull(typeOf<List<IntBox>>())
248+
assertNotNull(listSerializer)
249+
assertEquals("kotlin.collections.ArrayList(PrimitiveDescriptor(CIS))", listSerializer.descriptor.toString())
250+
251+
val genericSerializer = module.serializerOrNull(typeOf<GenericHolder<IntBox>>())
252+
assertNotNull(genericSerializer)
253+
assertEquals(
254+
"PrimitiveDescriptor(Generic Serializer parametrized by PrimitiveDescriptor(CIS))",
255+
genericSerializer.descriptor.toString()
256+
)
257+
}
258+
221259
@Test
222260
fun testContextualLookupNullable() {
223261
val module = SerializersModule { contextual(CustomIntSerializer(true).cast<IntBox>()) }

0 commit comments

Comments
 (0)