Search code examples
kotlinkotlinx.serializationkotlinx

How to intercept deserialisation with kotlinx.serialization


For example, I have JSON

{
  "url": "//n.ya.com"
}

In order to deserialize, I define the data class

@Serializable
data class Foo(
    @SerialName("url")
    val link: String,
)

After deserializing the Foo object has

foo.link with "//n.ya.com"

How can I remove the // during the deserializing, which means foo.link with "n.ya.com"?


Solution

  • You can add custom Serializer for a single property:

    @Serializable
    data class Foo(
        @SerialName("url")
        @Serializable(with = FooLinkDeserializer::class)
        val link: String,
    )
    
    object FooLinkSerializer : KSerializer<String> {
        override val descriptor = PrimitiveSerialDescriptor("Foo.link", PrimitiveKind.STRING)
    
        override fun deserialize(decoder: Decoder): String {
            return decoder.decodeString().substringAfter("//")
        }
    
        override fun serialize(encoder: Encoder, value: String) {
            encoder.encodeString("//$value")
        }
    }
    

    Or you can intercept JSON transformations using JsonTransformingSerializer:

    @Serializable
    data class Foo(
        @SerialName("url")
        @Serializable(with = FooLinkInterceptor::class)
        val link: String,
    )
    
    object FooLinkInterceptor : JsonTransformingSerializer<String>(String.serializer()) {
        override fun transformDeserialize(element: JsonElement): JsonElement {
            return JsonPrimitive(element.jsonPrimitive.content.substringAfter("//"))
        }
    }