how do I use a delegate serializer and deserialize...
# serialization
b
how do I use a delegate serializer and deserialize the value without consuming it first? my understanding based on the method signatures is that calling decoder.decodeX() consumes the token, correct? I'm trying to do this:
Copy code
object LanguageIsoSerializer : KSerializer<LanguageIso?> {
    private val delegate = serializer<LanguageIso>().nullable
    private val parsingDelegate = serializer<String>().nullable

    override val descriptor: SerialDescriptor
        get() = SerialDescriptor("at.fyayc.emporixapi.i18n.LanguageIso", delegate.descriptor)

    override fun serialize(
        encoder: Encoder,
        value: LanguageIso?
    ) {
        delegate.serialize(encoder, value)
    }

    override fun deserialize(decoder: Decoder): LanguageIso? {
        val string = parsingDelegate.deserialize(decoder)
        return if (string.isNullOrBlank()) {
            null
        } else {
            delegate.deserialize(decoder)
        }
    }
}
Technically I could use the parsed string and just iterate over enum entries, but that would ignore any annotation on the enum itself like @SerialName
✅ 1
e
if it's JSON,
Copy code
(decoder as JsonDecoder).json.decodeFromElement(delegate, JsonPrimitive(string))
there isn't a general way to do this for other formats
b
so basically wrap it in an element again, then pass it to the second deserializer
e
actually what I'd do is not use
parsingDelegate
and instead use
(decoder as JsonDecoder).decodeJsonElement()
but it works out the same
p
Another option may be to use JsonTransforming and transform blank to null
e
oh and as it's an enum, another option is to use its descriptor which has all the serial names of the entries
b
@phldavies thanks, will take a look at that as well, trying to grasp both solutions
Copy code
override fun deserialize(decoder: Decoder): LanguageIso? {
        if (decoder !is JsonDecoder) throw SerializationException("Can only deserialize JSON")
        val string = parsingDelegate.deserialize(decoder)
        return if (string.isNullOrBlank()) {
            null
        } else {
            // since string was consumed from parser stream, if we just passed the decoder, it'd be gone
            // so instead, wrap it in a JSON element again
            decoder.json.decodeFromString<LanguageIso>(string)
        }
    }
like this?
b
right I meant your solution
e
yes
their suggestion is
Copy code
object LanguageIsoSerializer : JsonTransformingSerializer<LanguageIso?>(LanguageIso.serializer().nullable) {
    override fun transformDeserialize(element: JsonElement): JsonElement =
    if (<http://element.primitive.content.is|element.primitive.content.is>Empty()) JsonNull else element 
}
which may be better suited for your specific case
b
thank you, was just trying to work it out but you were faster 🙂
Copy code
object LanguageIsoSerializer2 : JsonTransformingSerializer<LanguageIso?>(serializer<LanguageIso>().nullable) {
    override fun transformDeserialize(element: JsonElement): JsonElement =
        if (element is JsonPrimitive && element.content.isBlank()) {
            JsonNull
        } else {
            element
        }
}
hah, the super class basically does exactly the same
Copy code
final override fun deserialize(decoder: Decoder): T {
        val input = decoder.asJsonDecoder()
        val element = input.decodeJsonElement()
        return input.json.decodeFromJsonElement(tSerializer, transformDeserialize(element))
    }