MR3Y
03/19/2023, 1:55 PM{
"properties": {
"id": 1,
"name": "Foo",
"description": "FooFooFooFooFooFoo"
}
}
or this:
{
"id": 290375,
"properties": {
"id": 3,
"name": "Bar"
}
}
So, to deserialize it, I've defined Foo
& Bar
models respectively that inherit from FooBar
parent, and written a JsonContentPolymorphicSerializer
to choose the deserialization strategy accordingly, and finally I've registered this serializer in the `Json`'s SerializationModule
but that results in the following exception being thrown at runtime:
Serializer for FooBar can't be registered as a subclass for polymorphic serialization because its kind SEALED is not concrete. To work with multiple hierarchies, register it as a base class.
java.lang.IllegalArgumentException: Serializer for FooBar can't be registered as a subclass for polymorphic serialization because its kind SEALED is not concrete. To work with multiple hierarchies, register it as a base class.
what does this message mean? & how to solve it, Any ideas?
Code & small minimal reproducible test in the thread 🧵import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.*
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.polymorphic
import kotlinx.serialization.modules.subclass
import org.junit.Test
class FooBarSerializersTest {
private val fooBarSerializersModule = SerializersModule {
polymorphic(FooBar::class, baseSerializer = FooBarSerializer) {
subclass(Foo::class)
subclass(Bar::class)
}
}
private val json = Json {
serializersModule = fooBarSerializersModule
}
// Running this should fail!
@Test
fun deserializeToFooOrBar() {
val foo = json.decodeFromString<Foo>("""
{
"properties": {
"id": 1,
"name": "Foo",
"description": "FooFooFooFooFooFoo"
}
}
""".trimIndent())
assert(foo == Foo(properties=FooBarProperties(id=1, name="Foo", description="FooFooFooFooFooFoo")))
val bar = json.decodeFromString<Bar>("""
{
"id": 290375,
"properties": {
"id": 3,
"name": "Bar"
}
}
""".trimIndent())
assert(bar == Bar(id=290375, properties=FooBarProperties(id=3, name="Bar", description=null)))
}
}
object FooBarSerializer : JsonContentPolymorphicSerializer<FooBar>(FooBar::class) {
override fun selectDeserializer(element: JsonElement): DeserializationStrategy<FooBar> {
return when {
"id" in element.jsonObject -> Bar.serializer()
else -> Foo.serializer()
}
}
}
@Serializable
abstract class FooBar {
abstract val properties: FooBarProperties
}
@Serializable
data class Foo(override val properties: FooBarProperties): FooBar()
@Serializable
data class Bar(val id: Long, override val properties: FooBarProperties): FooBar()
@Serializable
data class FooBarProperties(
val id: Int,
val name: String,
val description: String? = null,
)