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

时间:2019-09-05 08:57:00

标签: json kotlin serialization polymorphism sealed-class

假设我有以下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
        }
    }
}

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

1 个答案:

答案 0 :(得分:3)

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

从文档中

  

提示:要使用不带包装的Message,可以传递PolymorphicSerializer(Message :: class)进行解析/字符串化。

您可以这样做:

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
        }
    }
}