Mikhail
10/26/2023, 8:07 AM@Serializable
sealed interface OperationResult<T>
@Serializable
class OperationSuccess<T>(val value: T): OperationResult<T>
In case of OperationSuccess<Goal>
(where Goal
is my data class) I can register value type for serialization/deserialization using:
Json {
serializersModule = SerializerModule {
polymorphic(Any::class) {
subclass(Goal::class)
}
}
}
But in case of OperationSuccess<List<Goal>>
I get runtime error:
Class 'SingletonList' is not registered for polymorphic serialization in the scope of 'Any'.
To be registered automatically, class 'SingletonList' has to be '@Serializable', and the base class 'Any' has to be sealed and '@Serializable'.
Alternatively, register the serializer for 'SingletonList' explicitly in a corresponding SerializersModule.
kotlinx.serialization.SerializationException: Class 'SingletonList' is not registered for polymorphic serialization in the scope of 'Any'.
To be registered automatically, class 'SingletonList' has to be '@Serializable', and the base class 'Any' has to be sealed and '@Serializable'.
Alternatively, register the serializer for 'SingletonList' explicitly in a corresponding SerializersModule.
How can I register list serializer as polymorphic for Any?
Is there a way to serialize/deserialize wrapper with collection inside?Mikhail
10/26/2023, 11:26 AM@Serializable(with = OperationResultSerializer::class)
sealed interface OperationResult<T>
@Serializable
class OperationSuccess<T>(val value:T): OperationResult<T>
@Serializable
class OperationFailed(val error: String): OperationResult<Nothing>
@OptIn(InternalSerializationApi::class)
class OperationResultSerializer<T>(valueSerializer: KSerializer<T>): KSerializer<OperationResult<T>> {
private val serializer = SealedClassSerializer(
OperationResult::class.simpleName!!,
OperationResult::class,
arrayOf(OperationSuccess::class, OperationFailed::class),
arrayOf(OperationSuccess.serializer(valueSerializer), OperationFailed.serializer())
)
override val descriptor: SerialDescriptor = serializer.descriptor
@Suppress("UNCHECKED_CAST")
override fun deserialize(decoder: Decoder): OperationResult<T> { return serializer.deserialize(decoder) as OperationResult<T> }
override fun serialize(encoder: Encoder, value: OperationResult<T>) { serializer.serialize(encoder, value) }
}
All magic are inside of SealedClassSerializer
And now serialization/deserialization of OperationResult<List<Int>>
works perfectly