-
Notifications
You must be signed in to change notification settings - Fork 626
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix serializer lookup by KType for third party generics (#1397)
This lookup used to fail, because `SerializersModule.serializerByKTypeImpl()` never tried `getContextual()` after constructSerializerForGivenTypeArgs() fails to find a serializer (and that *will* fail, because `ThirdPartyBox` is not annotated as @serializable, since it is a third party class). This does work when doing the look up by Java type with `serializerByJavaTypeImpl.serializerByJavaTypeImpe()`. This commit adds the call to `reflectiveOrContextual()` to `SerializersModule.serializerByKTypeImpl()`. The accompanying test illustrates the scenario where this used to fail.
- Loading branch information
Showing
4 changed files
with
65 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
45 changes: 45 additions & 0 deletions
45
core/commonTest/src/kotlinx/serialization/features/ThirdPartyGenericsTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package kotlinx.serialization.features | ||
|
||
import kotlinx.serialization.* | ||
import kotlinx.serialization.descriptors.* | ||
import kotlinx.serialization.encoding.* | ||
import kotlinx.serialization.modules.* | ||
import kotlin.test.* | ||
|
||
open class ThirdPartyGenericsTest { | ||
// This is a 3rd party class that we can't annotate as @Serializable | ||
data class ThirdPartyBox<T>(val contents: T) | ||
|
||
// This is the item that we put in the ThirdPartyBox, we control it, so can annotate it | ||
@Serializable | ||
data class Item(val name: String) | ||
|
||
// The serializer for the ThirdPartyBox<T> | ||
class BoxSerializer<T>(dataSerializer: KSerializer<T>) : KSerializer<ThirdPartyBox<T>> { | ||
@Serializable | ||
data class BoxSurrogate<T>(val contents: T) | ||
|
||
private val strategy = BoxSurrogate.serializer(dataSerializer) | ||
override val descriptor: SerialDescriptor = strategy.descriptor | ||
|
||
override fun deserialize(decoder: Decoder): ThirdPartyBox<T> { | ||
return ThirdPartyBox(decoder.decodeSerializableValue(strategy).contents) | ||
} | ||
|
||
override fun serialize(encoder: Encoder, value: ThirdPartyBox<T>) { | ||
encoder.encodeSerializableValue(strategy, BoxSurrogate(value.contents)) | ||
} | ||
} | ||
|
||
// Register contextual serializer for ThirdPartyBox<Item> | ||
protected val boxWithItemSerializer = BoxSerializer(Item.serializer()) | ||
protected val serializersModule = SerializersModule { | ||
contextual(boxWithItemSerializer) | ||
} | ||
|
||
@Test | ||
fun testSurrogateSerializerFoundForGenericWithKotlinType() { | ||
val serializer = serializersModule.serializer<ThirdPartyBox<Item>>() | ||
assertEquals(boxWithItemSerializer.descriptor, serializer.descriptor) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
core/jvmTest/src/kotlinx/serialization/features/JvmThirdPartyGenericsTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package kotlinx.serialization.features | ||
|
||
import kotlinx.serialization.* | ||
import kotlin.test.* | ||
|
||
class JvmThirdPartyGenericsTest : ThirdPartyGenericsTest() { | ||
@Test | ||
fun testSurrogateSerializerFoundForGenericWithJavaType() { | ||
val filledBox = ThirdPartyBox(contents = Item("Foo")) | ||
val serializer = serializersModule.serializer(filledBox::class.java) | ||
assertEquals(boxWithItemSerializer.descriptor, serializer.descriptor) | ||
} | ||
} |