KotlinX 序列化 - 使用密封的多态内容

KotlinX serialization - Polymorphic content using sealed

假设我有以下 json 个对象:

{
    "type": "video",
    "...": "..."
}
{
    "type": "image",
    "...": "..."
}

它们都代表媒体对象。 Kotlin 密封模型看起来像:

sealed class Media {
    ...
}

@Serializable
@SerialName("video")
data class Video(...) : Media()

@Serializable
@SerialName("image")
data class Image(...) : Media()

根据 KoltinX 文档,我使用了一个包装器来进行多态序列化:

@Serializable
private data class MediaWrapper(@Polymorphic val media: Media) {
    companion object {
        val jsonSerializer = Json(
            context = SerializersModule {
                polymorphic<Media> {
                    Video::class with Video.serializer()
                    Image::class with Image.serializer()
                }
            }
        )

        fun fromJson(json: String) = jsonSerializer.parse(serializer(), json)
    }
}

目标是使用我的包装器反序列化 Media json,但问题是我需要将 Media json 更改为 MediaWrapper json。 我找到的最方便的解决方案是在 Media json 的每一侧添加 {\"media\":\" & \"}

sealed class Media {
    companion object {
        fun fromJson(mediaJson: String): Media {
            val mediaWrapperJson = "{\"media\":$mediaJson}"
            val mediaWrapper = MediaWrapper.fromJson(mediaWrapperJson)
            return mediaWrapper.media
        }
    }
}

这是一个技巧,如果有更方便的反序列化多态的方法,请告诉我!

虽然 kotlinx 序列化文档在其许多多态示例中使用了包装器,但并未说明此模式是强制性的。

来自文档:

Pro tip: to use Message without a wrapper, you can pass PolymorphicSerializer(Message::class) to parse/stringify.

在你的情况下你可以这样做:

sealed class Media {
    companion object {
        val jsonSerializer = Json(
            context = SerializersModule {
                polymorphic<Media> {
                    Video::class with Video.serializer()
                    Image::class with Image.serializer()
                }
            }
        )

        fun fromJson(mediaJson: String): Media {
           return jsonSerializer.parse(PolymorphicSerializer(Media::class), mediaJson) as Media
        }
    }
}