https://kotlinlang.org logo
#serialization
Title
# serialization
f

Feri Nagy

11/14/2023, 11:53 AM
Hello. I ran into a wall when trying to use serialization for following weird format:
Copy code
{
  "-1":{
    "name":"Foo",
  },
  "182":{
    "name":"Bar",
  },
  "recordsCount":2
}
It is basically
Map<String, CustomType>
, but with added
recordsCount: Int
with the size of the map. We don’t own the api, so we are stuck with the structure. Any idea how to deserialize the map from the response? I thought we could somehow ignore the
recordsCount
property or write a custom serializer, but did not find a way to do either. Any idea how to go about this?
a

andylamax

11/14/2023, 11:55 AM
use JsonObject serializer for this
f

Feri Nagy

11/14/2023, 12:34 PM
Thanks for the hint. I was now able to use
JsonTransformingSerializer
for this. If anyone is interested in the code:
Copy code
@Serializable(with = FooResponseSerializer::class)
data class FooResponse(
    val data: Map<String, String>,
)

object FooResponseSerializer : KSerializer<FooResponse>  {

    private val delegateSerializer = WrappingSerializer
    override val descriptor: SerialDescriptor = SerialDescriptor("FooResponse", delegateSerializer.descriptor)

    override fun deserialize(decoder: Decoder): FooResponse {
        val map = decoder.decodeSerializableValue(delegateSerializer)
        return FooResponse(map)
    }

    override fun serialize(encoder: Encoder, value: FooResponse) {
        encoder.encodeSerializableValue(delegateSerializer, value.data)
    }
}


object WrappingSerializer : JsonTransformingSerializer<Map<String, String>>(MapSerializer(String.serializer(), String.serializer())) {

    override fun transformDeserialize(element: JsonElement): JsonElement {
        require(element is JsonObject)
        val filtered = JsonObject(content = element.filterNot { it.key == "recordsCount" })
        return super.transformDeserialize(filtered)
    }

    override fun transformSerialize(element: JsonElement): JsonElement {
        require(element is JsonObject)
        val added = element + ("recordsCount" to JsonPrimitive(element.size))
        return super.transformSerialize(JsonObject(added))
    }
}