Is it possible to globally override the built-in s...
# serialization
m
Is it possible to globally override the built-in serializer for a primitive type, such as
Boolean
, without requiring explicit
@Contextual
annotations on every field?
More details: I’m migrating from
Gson
and need to handle diverse
Boolean
representations (e.g., `true`/`false`, `"true"`/`"false"`, `1`/`0`, `"1"`/`"0"`, `1.0`/`0.0`) due to legacy backend inconsistencies. I’ve created a custom
KSerializer
for
Boolean
and registered it as a contextual serializer in my
Json
instance:
Copy code
private val json: Json = Json {
    serializersModule = SerializersModule {
        contextual(Boolean::class, MyCustomBooleanSerializer())
    }
}
However, Boolean fields are still deserialized using the default built-in serializer unless I explicitly annotate them with
@Contextual
. It appears that contextual serializers are only resolved when a built-in serializer is not found (as seen in SerializersModule.reflectiveOrContextual). Is there a way to prioritize my custom serializer over the built-in one for all instances of
Boolean
, without requiring per-field annotations? Or, is there any other approach to achieve global overriding of built-in serializers for primitive types?
Given this data class and
Json
instance :
Copy code
class MyCustomBooleanSerializer : KSerializer<Boolean> {
    // ... custom deserialization logic to handle "1", "0", "true", "false", etc.
}

val json = Json {serializersModule = SerializersModule { contextual( MyCustomBooleanSerializer()) }

@Serializable data class MyData(val value: Boolean)
I expect this deserialization to work:
Copy code
json.decodeFromString<MyData>("""{"value": "1"}""")
however, it fails with
Copy code
kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 11: Expected valid boolean literal prefix, but had '1' at path: $.value
JSON input: {"value": 1}
if I annotate the value with
@Contextual
it works as expected:
Copy code
@Serializable data class MyData( @Contextual val value: Boolean)
e
I don't think there's a way beyond modifying the serial format itself (e.g. an extension of
JsonConfiguration.isLenient
mode)
r
Whenever I've needed to do something like this I've had to create custom encoders that delegate everything but the type I care about to the base encoder I want to use. This is not the first time this has come up in this channel, but I'm not aware of a current issue for it
m
I’ve had to create custom encoders that delegate everything but the type I care about to the base encoder I want to use.
@rnett that will work for me too. how can I write my custom encoder/decoder? I couldn’t see anything about that in docs
r
Look at the docs for custom formats
👍 1
m
thanks, found it 👍