How can I ensure T has Serializable, and call .ser...
# announcements
a
How can I ensure T has Serializable, and call .serializer() ?
m
You can't. Serializers can be created for any types even if they aren't
@Serializable
. Why do you need them to be of a specific type? The library uses
SerialModule
for registering additional serializers at runtime.
a
I guess I'm not understanding how to get a serializer instance from T
And also pass json.parse<T> - I get an error because the type is refied
I would like to convert this code to a generic Serde<T>
Copy code
class QueryRequestSerde: Serde<QueryRequest> {
    override fun configure(configs: MutableMap<String, *>?, isKey: Boolean) {}

    override fun deserializer(): Deserializer<T> = QueryRequestDeSerializer()

    override fun close() {}

    override fun serializer(): Serializer<QueryRequest> = QueryRequestSerializer()
}

class QueryRequestDeSerializer: Deserializer<QueryRequest> {
    private val json = Json(JsonConfiguration.Stable)

    override fun configure(configs: MutableMap<String, *>?, isKey: Boolean) {}

    @ImplicitReflectionSerializer
    override fun deserialize(topic: String?, data: ByteArray?): T? {
        return if (data != null)
            json.parse(QueryRequest.serializer(), data.toString(Charsets.UTF_8))
        else null
    }

    override fun close() {}
}

class QueryRequestSerializer: Serializer<QueryRequest> {
    override fun configure(configs: MutableMap<String, *>?, isKey: Boolean) {}

    @ImplicitReflectionSerializer
    override fun serialize(topic: String?, data: QueryRequest?): ByteArray? {
        return if (data != null)
            json.stringify(QueryRequest.serializer()).toByteArray(Charsets.UTF_8)
        else null
    }

    override fun close() {}

    private val json = Json(JsonConfiguration.Stable)
}
m
It
T
is
@Serializable
and not generic then you can use
T::class.serializer()
. That means you need the
KClass
of
T
.
Then you call
.stringify()
with both, the serializer and the instance to serialize.
So when you create an instance of
YourGenericSerde
you'll likely have to pass the
KClass<T>
to it because you have no other way of accessing it.
Even better would be to pass
KSerializer
directly for more flexibility and you wouldn't have to rely on reflection which btw only works on the JVM.
a
Copy code
@Serializable
data class QueryRequest(val metrics: List<MetricQueryRequest>) {
    companion object {
        val serde = JsonSerde(serializer())
    }
}

data class MetricQueryRequest(val metricDefinition: String, val parameters: Map<String, *>)


class JsonSerde<T>(private val serializer: KSerializer<T>): Serde<T> {
    private val json = Json(JsonConfiguration.Stable)

    override fun deserializer(): Deserializer<T> = JsonDeserializer()
    override fun serializer(): Serializer<T> = JsonSerializer()

    override fun configure(configs: MutableMap<String, *>?, isKey: Boolean) {}
    override fun close() {}

    inner class JsonDeserializer: Deserializer<T> {
        @ImplicitReflectionSerializer
        override fun deserialize(topic: String?, data: ByteArray?): T? {
            return if (data != null)
                json.parse(serializer, data.toString(Charsets.UTF_8))
            else null
        }

        override fun close() {}
        override fun configure(configs: MutableMap<String, *>?, isKey: Boolean) {}
    }

    inner class JsonSerializer: Serializer<T> {
        override fun serialize(topic: String?, data: T): ByteArray? {
            return if (data != null)
                json.stringify(serializer, data).toByteArray(Charsets.UTF_8)
            else null
        }

        override fun configure(configs: MutableMap<String, *>?, isKey: Boolean) {}
        override fun close() {}
    }
}
Looks like it will work, thanks for the help
👍 1