0

I have the following response from a backend:

{
  "title": "House",
  "translations": {
    "es": "Casa",
    "fr": "Maison",
    "de": "Haus"
  }
}

To process it I am using the kotlinx serializer and this is my data class.

@Serializable
data class MyRespons(
    val title: String,
    val translations: Map<String,String>? = null,
)

The property translations is optional, so in some cases I can just get the title (which is fine). What the problem is, is that there also cases where the backend returns this json:

{
   "title": "House",
   "translations": ""
 }

This throws an error because Kotlin is not converting the empty string to a null map but tries to get the properties from it. Is there a way to make Kotlin treat an empty string as if the property was not set at all? (I am trying to not make a custom serializer for this, especially because the map serializer has lots of code...)

Sadly I can't change this backend behavior and have to live with it.

rimes
  • 761
  • 1
  • 8
  • 25
  • I've never used kotlinx-serialization, but I don't think your remark about rewriting lots of code for the Map serializer is necessarily correct. If you serialize to a custom type that wraps around a Map, I think you can just check if the string is empty and return null, if not delegate to the default Map deserializer https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/serializers.md#delegating-serializers – somethingsomething Oct 25 '22 at 14:18
  • 1
    You might not even need a custom type if kotlinx allows you to define which deserializer to use for a single specific serialization, which it looks like you can. https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json/decode-from-string.html – somethingsomething Oct 25 '22 at 14:24
  • I forgot to tell that I am not converting the response manually, but it is being done with ktor right inside the request. I was hoping that there is an annotation or something similar but as it seems there is not. I also found out about _JsonTransformingSerializer_ where I don't need to implement everything but just the deserializer. – rimes Oct 26 '22 at 04:59
  • To be fair, and I know this isn't an answer, but it's API's fault; it should be sending an empty list `{ }` not an empty string. – rtsketo Nov 02 '22 at 11:04

1 Answers1

0

you can wrap Map Serializer with:

object MapSerializer: KSerializer<Map<String,String>> {
override val descriptor: SerialDescriptor
    get() = TODO("Not yet implemented")

override fun deserialize(decoder: Decoder): Map<String, String> {
    if (decoder.decodeString().isEmpty())
        return mapOf()
    else
        return MapSerializer(String.serializer(),String.serializer()).deserialize(decoder)
}

}

A-_-S
  • 680
  • 5
  • 21