Gson deserialization for compose color

58 views Asked by At

In my project I want to deserialize JSON that has androidx.compose.ui.graphics.Color using Gson. My simplified data class looks like this:

data class Colors(val color: Color)

I wanted to add custom adapter for Color type:

fun main() {

    val colors = GsonBuilder()
        .registerTypeAdapter(Color::class.java, ColorAdapter())
        .create()
        .fromJson("{color: \"#FFFFFF\"}", Colors::class.java)

    println(colors)
}

class ColorAdapter : TypeAdapter<Color>() {
    override fun write(out: JsonWriter?, value: Color?) {
        TODO("Not yet implemented")
    }

    override fun read(reader: JsonReader): Color {
        val color = reader.nextString()
        return Color(color.removePrefix("#").toLong(radix = 16))
    }
}

And its read was never invoked, and app crashed because of format, so I tried some other approach. To add adapter like this

.registerTypeHierarchyAdapter(Long::class.java, ColorAdapter())

In that case, read was invoked, but error happened: Exception in thread "main" com.google.gson.JsonSyntaxException: Expected a long but was androidx.compose.ui.graphics.Color

Reason for this is probably inside definition of Color:

@Immutable
@kotlin.jvm.JvmInline
value class Color(val value: ULong)

but in any case, I did not find any solution for that.

Question is how could I accomplish this without changing field and adapter to use Long, as that is my only option for now.

1

There are 1 answers

0
Ivo On BEST ANSWER

Also defining a TypeAdapter (or JsonDeserializer) for the Colors class seems to do the trick. This for example works:

package org.example
import androidx.compose.ui.graphics.Color
import com.google.gson.GsonBuilder
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import java.lang.reflect.Type

data class Colors(val color: Color)

fun main() {

    val colors = GsonBuilder()
        .registerTypeAdapter(Colors::class.java, ColorsAdapter())
        .registerTypeAdapter(Color::class.java, ColorAdapter())
        .create()
        .fromJson("{color: \"#FFFFFF\"}", Colors::class.java)

    println(colors)
}

class ColorsAdapter : JsonDeserializer<Colors> {
    override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Colors {
        return Colors(context.deserialize(json.asJsonObject.get("color"), Color::class.java))
    }
}

class ColorAdapter : JsonDeserializer<Color> {
    override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Color {
        return Color(json.asString.removePrefix("#").toInt(16))
    }
}