Closed williamboxhall closed 1 year ago
Related issue over in kotlinx-serialization
https://github.com/Kotlin/kotlinx.serialization/issues/1417
Did you find a workaround for this @williamboxhall ?
@rocketraman no workaround unfortunately - luckily for me I was able to get away with translating my heirarchy into a sealed class rather than using sealed interfaces. But I know this won't always be possible in future so would love proper support for this.
Implemented with #111
As it turns out there are multiple problems with supporting sealed interfaces. As it seems, the upcoming kotlin 1.6.20 will support sealed interfaces natively (see https://github.com/JetBrains/kotlin/commit/de128a5406fcbc4cfcfdc7f136eea0e1885dddb0 and https://github.com/Kotlin/kotlinx.serialization/issues/1576). Therefore the custom implementation will be removed until the offical support exists. When sealed interfaces will be officially supported by kotlinx.serialization, this ticket should be used to check the avro4k compatibility.
If you still need (partial) support for sealed interfaces in the mean time, you can use the following code snippet to register the serializers:
@file:OptIn(InternalSerializationApi::class)
@file:Suppress("UNCHECKED_CAST")
package com.github.avrokotlin.avro4k
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.modules.SerializersModuleBuilder
import kotlinx.serialization.serializer
import kotlin.reflect.KClass
/**
* Registers all direct subclasses of a sealed type as polymorphic types.
*/
fun <T : Any> SerializersModuleBuilder.polymorphicForSealed(sealedType: KClass<T>) {
if (!sealedType.isSealed) throw IllegalArgumentException(
"Type $sealedType is not sealed."
)
sealedType.sealedSubclasses.forEach {
polymorphic(sealedType, it as KClass<T>, it.serializer())
}
}
/**
* Registers all subclasses of a sealed type tree as polymorphic types. In contrast to polymorphicForSealed this method
* also adds subclasses of sealed subclasses as polymorphic types.
*/
fun <T : Any> SerializersModuleBuilder.polymorphicTreeForSealed(sealedType: KClass<T>) {
if (!sealedType.isSealed) throw IllegalArgumentException(
"Type $sealedType is not a sealed type."
)
sealedType.sealedSubclasses.forEach {
polymorphic(sealedType, it as KClass<T>, it.serializer())
if(it.isSealed) {
polymorphicTreeForSealed(it)
}
}
}
Current main supports sealed interfaces
I'm using a sealed interface and when I try to generate an avro schema for the sealed hierarchy I get:
it looks like
kotlinx-serialization
thinks this class isSerialKind.OPEN
instead ofSerialKind.SEALED
so I guess this could be akotlinx-serialization
issue with sealed interfaces (not sure if being across multiple files matters)