Kotlinx.Serialization deserializing dates

15.8k views Asked by At

I'm having a hard time finding documentation on how to deserialize date fields. How do i achieve this? Most solutions i found on SO don't work or they use classes that are no longer available

@Serializable
data class Dashboard(
    val someNumber: Int,
    val someDate: Date? // Custom Deserialization from unix timestamp
)

EDIT: Most solution i found use PrimitiveSerialDescriptor which seems to be not available

3

There are 3 answers

0
Aleksandr Baklanov On

There is good documentation for the latest version of kotlinx.serialization https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/serializers.md#custom-serializers

However, there is no PrimitiveSerialDescriptor class in the question which means, that some older version of kotlinx.serialization is used.

From https://github.com/Kotlin/kotlinx.serialization/releases it could be found out that in version 1.0.0-RC

PrimitiveDescriptor was renamed to PrimitiveSerialDescriptor

and

The id of the core artifact with @Serializable annotation and Json format was changed from kotlinx-serialization-runtime to kotlinx-serialization-core to be more clear and aligned with other kotlinx libraries.

Following that, here is an example of code for kotlinx.serialization version 0.20.0:

object DateSerializer : KSerializer<Date> {
    override val descriptor = PrimitiveDescriptor("Date", PrimitiveKind.LONG)
    override fun serialize(encoder: Encoder, value: Date) = encoder.encodeLong(value.time)
    override fun deserialize(decoder: Decoder): Date = Date(decoder.decodeLong())
}

@Serializable
data class MyDto(
    @Serializable(DateSerializer::class)
    val date: Date
)

fun main() {
    val dto = Json.parse(MyDto.serializer(), """{ "date" : 1630407000000 }""")
    println(dto.date)
}

with build.gradle.kts

plugins {
    kotlin("jvm") version "1.3.72"
    kotlin("plugin.serialization") version "1.3.72"
}
repositories { mavenCentral() }
dependencies {
    implementation("org.jetbrains.kotlinx", "kotlinx-serialization-runtime", "0.20.0")
}
0
All Іѕ Vаиітy On

To deserialize

import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializer
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale


@OptIn(ExperimentalSerializationApi::class)
@Serializer(forClass = Date::class)
object DateSerializer {
    private val format = SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH)

    override fun deserialize(decoder: Decoder): Date {
        val dateString = decoder.decodeString()
        return format.parse(dateString)
    }

    override fun serialize(encoder: Encoder, value: Date) {
        val dateString = format.format(value)
        encoder.encodeString(dateString)
    }
}

then in your @Serializable class,

@Serializable(with = DateSerializer::class)
val date: Date,

the dependencies at app level build.gradle file.

implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0'

you may need to play around with the format "yyyy-MM-dd" as this answer deals with 2023-June-05 format.

5
Tom William On

Do not use Date, but use Instant or LocalDateTime instead, you need to add this in build.gradle file

implementation "org.jetbrains.kotlinx:kotlinx-datetime:0.3.2"

read more about it in this link: https://github.com/Kotlin/kotlinx-datetime

This will automatically Serializable and also work in KMM