Call default/plugin-generated serializer from custom serializer

Hi,

I am trying to use the default serialization lib to serialize a class hierarchy consisting of a super class Matrix and a sub class ColumnVector (ColumnVector is not adding any fields). as I want to be able to instantiate both, I cannot abstract / seal Matrix and therefore can’t use the polymorphic definition in the SerializersModule.

Therefore I’m trying to build a custom serializer that encodes the class I’m using into a separate element of the serialized structure and then appends the serialized object itself.

Is this possible or do I need to manually serialize all the fields of Matrix?
What would I use as type for the SerialDescriptor? Is there a way to access the default/plugin-generated serializer after I defined my own and specified it in the @Serialized(with = ...) annotation?

@Serializable(with = MatrixSerializer::class)
open class Matrix(var m: Array<Array<Complex>> = someDefaultValue) {...}

class ColumnVector(v: Array<Complex>) : Matrix(v.doSth()) { ... }

object MatrixSerializer : KSerializer<Matrix> {
    override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Matrix") {
        element<Boolean>("columnVector")
        element<???????>("m")
    }

    override fun serialize(encoder: Encoder, matrix: Matrix) {
        encoder.encodeStructure(descriptor) {
            encodeBooleanElement(descriptor, 0, matrix is ColumnVector)
            encodeSerializableElement(descriptor, 1, Matrix.serializer???(), matrix)
        }
    }

    override fun deserialize(decoder: Decoder): Matrix {
        TODO("Not yet implemented")
    }
}

Thanks.

Annotate ColumnVector with @Serializable as well. No need to create a custom serializer unless the problem you are facing has been omitted from the post!

1 Like

Thanks for your reply.
I can’t do that as ColumnVector has constructor parameters that are not variables but are just used for calling the constructor of the superclass.

1 Like

It is fairly easy to call a default serializer from a custom serializer. Looking at your question you actually want to access a generated serializer as well. It may be possible to have an private inner object to MatrixSerializer that is annotated with @Serializer(Matrix::class) that you delegate to. In this particular case it’s probably easier to just do it by hand.

As a sidenote, if your matrix is mutable (as it is here) it is not valid to have ColumnVector be a Matrix as it is possible to use matrix to make the ColumnVector no longer a valid matrix.

1 Like

I have tried something simillar. I wanted to get raw json in custom serializer and then just use default one. I think there should be 2 methods for getting serializers - serializer, which is current serializer for class and default one, which is non custom serializer. It would make life much easier.

I have tried few approaches, object with @Serializer(MyClass::class) too, but noone worked. I don’t like an idea of writing descriptor for such case, which can be easly done in gson or moshi for example. It adds too much code and complexity without good reason.

Finally I have created class with same objects, used it’s serializer and mapped to the class I wanted to get