在 Kotlin/Native 中使用 kotlinx.serialization 进行多态反序列化

Posted

技术标签:

【中文标题】在 Kotlin/Native 中使用 kotlinx.serialization 进行多态反序列化【英文标题】:Polymorphic deserialization with kotlinx.serialization in Kotlin/Native 【发布时间】:2021-06-07 18:19:51 【问题描述】:

我想在 Kotlin Multiplatform 项目中使用 kotlinx.serialization 解码包含多态类结构中对象列表的 json 字符串,但它仅适用于 JVM,不适用于 Native。这是一个最小的可重现示例:

@Serializable
abstract class Project 
    abstract val name: String


@Serializable
@SerialName("BasicProject")
data class BasicProject(override val name: String): Project()

@Serializable
@SerialName("OwnedProject")
data class OwnedProject(override val name: String, val owner: String) : Project()

fun main() 
    val data = Json.decodeFromString<List<Project>>("""
        [
            "type":"BasicProject","name":"example",
            "type":"OwnedProject","name":"kotlinx.serialization","owner":"kotlin" 
        ]
    """))
  

这适用于 JVM,但在 Native 上会引发以下异常:

kotlinx.serialization.SerializationException: Serializer for class ‘Project’ is not found.
Mark the class as @Serializable or provide the serializer explicitly.
On Kotlin/Native explicitly declared serializer should be used for interfaces and enums without @Serializable annotation.message

之前在编码的上下文中已经讨论过这个问题,并且已经提出了一些解决方法,例如here,但我的问题是解码。是否有解决方法,还是我只需实现自己的 json 解析器?

【问题讨论】:

实际上,如果没有为Json 明确指定serializersModule,即使在JVM 中也无法正常工作:val module = SerializersModule polymorphic(Project::class) subclass(BasicProject::class); subclass(OwnedProject::class) ; val data = Json serializersModule = module .decodeFromString&lt;List&lt;Project&gt;&gt;(...) 如果您指定上述serializersModule 并明确传递序列化程序,它将在 Kotlin/Native 中工作:object ListOfProjectSerializer : KSerializer&lt;List&lt;Project&gt;&gt; by ListSerializer(Project.serializer()); val data = Json serializersModule = module .decodeFromString(ListOfProjectSerializer, ...) 吗? 是的,非常感谢!如果您将其发布为答案,我会将其标记为已接受。 【参考方案1】:

您需要显式传递尊重的序列化程序和serializersModule

object ListOfProjectSerializer : KSerializer<List<Project>> by ListSerializer(Project.serializer())

val module = SerializersModule 
    polymorphic(Project::class) 
        subclass(BasicProject::class)
        subclass(OwnedProject::class)
    


fun main() 
    val data = Json  serializersModule = module .decodeFromString(
        ListOfProjectSerializer,
        """
        [
            "type":"BasicProject","name":"example",
            "type":"OwnedProject","name":"kotlinx.serialization","owner":"kotlin" 
        ]
        """
    )

【讨论】:

polymorphic() 现在需要三个参数,而不是两个 @DzmitryLazerka 此代码在当前最新的kotlinx.serialization (1.3.2) 中仍然有效。 polymorphic 方法有一个 overload, which is defined as an extension method 并在此处使用。它有 3 个参数,但其中两个有默认值。 @МихаилНафталь 链接无效。我找不到扩展方法。编辑:nvr 介意,我必须添加 import kotlinx.serialization.modules.* 看来,他们已经修改了文档;当前正确链接:kotlin.github.io/kotlinx.serialization/…

以上是关于在 Kotlin/Native 中使用 kotlinx.serialization 进行多态反序列化的主要内容,如果未能解决你的问题,请参考以下文章

如何在 kotlin native 中使用 swift 库?

kotlin.native.concurrent.InvalidMutabilityException:在 Kotlin Multiplatform (iOS) 中使用 ktor 时冻结 <ob

在 Cocoapod 中导入 Kotlin/Native 框架

链接 ktor 和 kotlinx.coroutines 会导致未定义的符号

在 Kotlin/Native 中使用 kotlinx.serialization 进行多态反序列化

使用协程的 Kotlin/Native 多线程