带有泛型的 Kotlin 序列化:未使用密封接口的插件生成的多态序列化器

问题描述 投票:0回答:1

使用 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
层次结构定义多态序列化器(取消注释上面的行)时,测试通过了。这是为什么?当我为容器定义多态序列化时,似乎没有使用自动生成的序列化程序。这是预期的吗?一个错误?或者我只是在定义序列化器模块时做错了什么?

kotlin generics serialization kotlinx.serialization
1个回答
0
投票

我想你已经发现了一个错误。

对密封接口的支持是相当新的,所以也许这并不是一个大惊喜。我注意到序列化指南中没有具体提及如何使用它们。就我个人而言,我(迄今为止)只是尝试使用密封的classes进行自动多态序列化。

我还注意到,如果您从

@Serializable
中删除
BaseContainer
注释,这也允许您的序列化工作。这是不对的:我们要么应该注释这样的接口(就像
Element
那样),要么不应该。

© www.soinside.com 2019 - 2024. All rights reserved.