Skip to content

Commit 3f8378d

Browse files
authored
Support retreiving serializer for sealed interface (#1968)
Fixes #1965
1 parent aedd915 commit 3f8378d

File tree

2 files changed

+54
-3
lines changed

2 files changed

+54
-3
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package kotlinx.serialization
2+
3+
import kotlinx.serialization.test.*
4+
import kotlin.test.*
5+
6+
class SerializersLookupInterfaceTest {
7+
8+
interface I
9+
10+
@Polymorphic
11+
interface I2
12+
13+
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
14+
@Serializable(PolymorphicSerializer::class)
15+
interface I3
16+
17+
@Serializable
18+
@SerialName("S")
19+
sealed interface S
20+
21+
// TODO: not working because (see #1207, plugin does not produce companion object for interfaces)
22+
// We even have #1853 with tests for that
23+
// @Serializable(ExternalSerializer::class)
24+
// interface External
25+
26+
27+
@Test
28+
fun testSealedInterfaceLookup() {
29+
if (currentPlatform == Platform.JS_LEGACY) return
30+
val serializer = serializer<S>()
31+
assertTrue(serializer is SealedClassSerializer)
32+
assertEquals("S", serializer.descriptor.serialName)
33+
}
34+
35+
@Test
36+
fun testInterfaceLookup() {
37+
// Native does not have KClass.isInterface
38+
if (currentPlatform == Platform.NATIVE || currentPlatform == Platform.JS_LEGACY) return
39+
40+
val serializer1 = serializer<I>()
41+
assertTrue(serializer1 is PolymorphicSerializer)
42+
assertEquals("kotlinx.serialization.Polymorphic<I>", serializer1.descriptor.serialName)
43+
44+
val serializer2 = serializer<I2>()
45+
assertTrue(serializer2 is PolymorphicSerializer)
46+
assertEquals("kotlinx.serialization.Polymorphic<I2>", serializer2.descriptor.serialName)
47+
48+
val serializer3 = serializer<I3>()
49+
assertTrue(serializer3 is PolymorphicSerializer)
50+
assertEquals("kotlinx.serialization.Polymorphic<I3>", serializer3.descriptor.serialName)
51+
}
52+
}

core/jvmMain/src/kotlinx/serialization/internal/Platform.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,8 @@ internal fun <T: Any> Class<T>.constructSerializerForGivenTypeArgs(vararg args:
4444
if (isEnum && isNotAnnotated()) {
4545
return createEnumSerializer()
4646
}
47-
if (isInterface) {
48-
return interfaceSerializer()
49-
}
47+
// Fall-through if the serializer is not found -- lookup on companions (for sealed interfaces) or fallback to polymorphic if applicable
48+
if (isInterface) interfaceSerializer()?.let { return it }
5049
// Search for serializer defined on companion object.
5150
val serializer = invokeSerializerOnCompanion<T>(this, *args)
5251
if (serializer != null) return serializer

0 commit comments

Comments
 (0)