kotlinx.serialization
kotlinx.serialization copied to clipboard
`JsonContentPolymorphicSerializer` should provide a non-final `selectSerializer`
What is your use-case and why do you need this feature?
JsonContentPolymorphicSerializer
is a very useful abstract class and I have used it quite a few times, but now I have a slightly different problem that cannot be fixed using it.
I'm basically trying to support serialization on a Map<String, Any>
where Any
could be String
or a a few classes that belong to a polymorphic hierarchy. (That would be a perfect case for a String | MyObject
union type, but we don't have that yet).
This is how I implemented it:
class TemplateVariablesSerializer: JsonContentPolymorphicSerializer<Any>(Any::class) {
override fun selectDeserializer(element: JsonElement): DeserializationStrategy<Any> {
return when (element) {
is JsonArray -> throw IllegalStateException("arrays are not supported yet")
is JsonObject -> serializer<MySealedHierarchy>()
is JsonPrimitive -> when {
element.isString -> serializer<String>()
else -> throw IllegalStateException("non-string primitive types are not supported yet")
}
}
}
}
Everything works great for deserialization if I have the correct payload, but for serialization we end up with a payload without the discriminator value as the serializer of the instance is used instead of the MySealedHierarchy
one.
Describe the solution you'd like
If we had something like
protected fun selectSerializer(encoder: Encoder, value: T): SerializationStrategy<T> {
encoder.serializersModule.getPolymorphic(baseClass, value)
?: value::class.serializerOrNull()
?: throwSubtypeNotRegistered(value::class, baseClass)
}
we could actually override the default serializer to consider the value type:
override fun selectSerializer(encoder: Encoder, value: T): SerializationStrategy<T> {
when (value) {
is MySealedHierarchy -> serializer<MySealedHierarchy>()
else -> super.selectSerializer(encoder, value)
}
}
https://github.com/Kotlin/kotlinx.serialization/issues/1247 might help with this one we have POLYMORPHIC_AND_SUBTYPES
, but I think having an override-able selectSerializer
is a good change anyway.