2

I want to use my own custom KSerializer<LocalDateTime> with kotlinx.serialization and kotlinx.datetime

@ExperimentalSerializationApi
@Serializer(forClass = LocalDateTime::class)
object LocalDateTimeSerializer : KSerializer<LocalDateTime> {
...

I create my Json like this:

    val JSON = Json {
        prettyPrint = true; prettyPrintIndent = " ".repeat(2)
        serializersModule = this.serializersModule.apply {
            overwriteWith(
                SerializersModule {
                    contextual(Instant::class, InstantSerializer)
                    contextual(LocalDateTime::class, LocalDateTimeSerializer)
                }
            )
        }
    }

but whatever I try, I cannot succeed to replace the default LocalDateTimeIso8601Serializer with mine:

    val l = JSON.decodeFromString<LocalDateTime>(s) // does NOT(!) use my own Serializer

    // have to give it explicitly to work, but that's not what I want
    val l = JSON.decodeFromString<LocalDateTime>(LocalDateTimeSerializer, s) // works, but explicitly

is it possible to replace a default Serializer??

anyone?

Dirk Hoffmann
  • 1,444
  • 17
  • 35
  • It looks unusual that you've annotated `LocalDateTimeSerializer` with `@Serializer(forClass...)`. [The example in the docs](https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/serializers.md#deriving-external-serializer-for-another-kotlin-class-experimental) sets it on an independent object. Can you provide a complete example? What version of Kotlin and Kotlinx Serialization are using? If you're using Kotlin Multiplatform, where does `LocalDateTime` come from? – aSemy Jun 04 '22 at 10:41
  • https://gitlab.com/hoffi_minimal/minimal_ktor – Dirk Hoffmann Jun 04 '22 at 13:20
  • 1
    It works with a @Contextual annotation on a property you want to use that contextual serializer on – Sam Jun 06 '22 at 14:47
  • ok, yes, but I explicitly wanna replace the default serializers. So that I don't have to add Annotations to each and everyone properties of these types – Dirk Hoffmann Jun 07 '22 at 17:30

1 Answers1

1

This is not possible.

The closest to what you want to achieve is by specifying a default serializer for a full file.

If I'm not mistaken, the reason for this is kotlinx serialization is a reflectionless serializer; all serializers are defined at compile time. Applying @Contextual is a way to disable that behavior and determine a serializer at runtime based on context (not what you are after here). I guess you could request a feature to apply a default serializer to a full module (likely already requested), but I can see how it's harder to implement/can lead to more unexpected conflicts/behavior than on file scope, which is why it may currently not be supported.

As a hack, you could consider using a wrapper type for LocalDateTime which uses your custom serializer. But, I'd recommend against this. Essentially, this is the same as applying the annotation everywhere, in that at every occurrence you need to make sure to use the right type.

Steven Jeuris
  • 18,274
  • 9
  • 70
  • 161