Let's assume I have following json objects :
{
"type": "video",
"...": "..."
}
{
"type": "image",
"...": "..."
}
They both represent media object. Kotlin sealed model looks like :
sealed class Media {
...
}
@Serializable
@SerialName("video")
data class Video(...) : Media()
@Serializable
@SerialName("image")
data class Image(...) : Media()
According KoltinX doc, I used a wrapper for polymorphic serialization :
@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)
}
}
The goal is to deserialize a Media
json using my wrapper, but problem is I need to change my Media
json into a MediaWrapper
json.
The most convenient solution I found is to add {\"media\":\"
& \"}
on each side of my Media
json:
sealed class Media {
companion object {
fun fromJson(mediaJson: String): Media {
val mediaWrapperJson = "{\"media\":$mediaJson}"
val mediaWrapper = MediaWrapper.fromJson(mediaWrapperJson)
return mediaWrapper.media
}
}
}
This is a trick, if there is a more convenient way to deserialize polymorphics, please let me know!
While the kotlinx serialization docs use a wrapper in many of its polymorphic examples, it does not say that this pattern is mandatory.
From the docs:
Pro tip: to use Message without a wrapper, you can pass PolymorphicSerializer(Message::class) to parse/stringify.
In your case you could do:
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
}
}
}