使用 kotlin 1.9.23 上的 kotlinx.serialization 1.6.3,我尝试使用受限制的泛型类型参数序列化类型层次结构(
BaseContainer
,请参阅示例)。泛型类型本身是一个密封的层次结构 (Element
)。据我了解,应该为这个密封的 Element
层次结构自动生成序列化器。但是,我无法将这些自动生成的序列化器用于参数化的 BaseContainer
层次结构。
这是一个最小的设置:
// This is the sealed hierarchy, for which serializers should be auto-generated:
@Serializable
sealed interface Element
@Serializable
data class CountElement(val elementCount: Int) : Element
@Serializable
data class FlagElement(val flag: Boolean) : Element
// This is a class hierarchy with generic type parameter E restricted to Element:
@Serializable
sealed interface BaseContainer<out E : Element>
@Serializable
data class ElementContainer<out E : Element>(
val element: E
) : BaseContainer<E>
// This is the serializers module to enable polymorphic serialization of the generic container classes
val containerSerializerModule = SerializersModule {
polymorphic(BaseContainer::class) {
subclass(ElementContainer.serializer(Element.serializer())) // alt: serializer<Element>()
}
// Commented out, so the auto-generated serializers of the sealed Element hierarchy are used.
// polymorphic(Element::class) {
// subclass(FlagElement::class)
// subclass(CountElement::class)
// }
}
// And here is a test to illustrate the problem
internal class GenericSerializerTest {
val json = Json { serializersModule = containerSerializerModule }
@Test
fun `polymorphically serialize and deserialize an element container`() {
val container = ElementContainer(FlagElement(false))
val containerJson = json.encodeToString(serializer<BaseContainer<Element>>(), container)
val containerDeserialized = json.decodeFromString(serializer<BaseContainer<Element>>(), containerJson)
assertEquals(container, containerDeserialized)
}
}
当我运行上述测试时,我收到以下错误消息:
kotlinx.serialization.SerializationException: Serializer for subclass 'FlagElement' is not found in the polymorphic scope of 'Element'.
但是,当我手动为 Element
层次结构定义多态序列化器(取消注释上面的行)时,测试通过了。这是为什么?当我为容器定义多态序列化时,似乎没有使用自动生成的序列化程序。这是预期的吗?一个错误?或者我只是在定义序列化器模块时做错了什么?
我想你已经发现了一个错误。
对密封接口的支持是相当新的,所以也许这并不是一个大惊喜。我注意到序列化指南中没有具体提及如何使用它们。就我个人而言,我(迄今为止)只是尝试使用密封的classes进行自动多态序列化。
我还注意到,如果您从
@Serializable
中删除 BaseContainer
注释,这也允许您的序列化工作。这是不对的:我们要么应该注释这样的接口(就像 Element
那样),要么不应该。