Is it possible to use kotlinx-datetime with Gson

606 views Asked by At

I have JSON data which is retrieved from the local realm database. I'm trying to convert it into the corresponding data class. I have an ISO date field

{
  ....
  "createdAt" : "2022-05-04T10:16:56.489Z"
  ....

}

What I'm trying to do is to convert this string date field into kotlinx-datetime's Instant object which is a serializable class. Thus I made my data class as

import kotlinx.datetime.Instant

data class PollPinComment(
    ...
    val createdAt: Instant? = null,
    ...
)

Which doesn't work and gives an error as follows

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 288 path $[0].createdAt

I'm sure that I might need to write some serialization/deserialization logic with gson to convert this string into Instant object. So my question is how can I do that? Thanks in advance

2

There are 2 answers

0
Praveen On

You can create a custom Deserializer for this and register it as type adapter to your Gson object.

class InstantDateDeserializer: JsonDeserializer<Instant> {
    override fun deserialize(
        json: JsonElement?, 
        typeOfT: Type?, 
        context: JsonDeserializationContext?
    ): Instant? {
        return json?.asString?.let {
            Instant.parse(it)
        }
    }
}

Create Gson() object pasing that deserializer as type adapter

val gson: Gson = GsonBuilder ()
    .registerTypeAdapter(Instant::class.java, InstantDateDeserializer())
    .create()

If you are using it with Retrofit

In Retrofit builder pass this to GsonConverterFactory

val retrofit = Retrofit.Builder()
    .baseUrl(BASE_URL)
    .addConverterFactory(GsonConverterFactory.create(gson))
    .build()
1
Matrix On

GSON parses only basic data types, such as Int, String, double... Other classes that need to be parsed must also consist of these basic data types. could do like this:

 data class PollPinComment(val createdAt: String ){

 fun  getCreatedAt(): Instant{
     return  Instant.parse(createdAt) 
 }
 }