Search code examples
intbooleangsonkotlindata-class

Kotlin data class Gson serialization issue


Im a little bit confused for my kotlin class didn't work as expected:

the data class used to check update info:

data class UpdateInfo constructor(//kotlin class
    val description: String,
    val force: Int,
    val platform: String,
    val title: String,
    val url: String,
    @SerializedName("version")
    val versionCode: Int = 0
) : Serializable {
    val isForceUpdate = force == 1
}

also a util used to decode object form json:

public class JsonUtil {//java class
    private static final Gson gson;
    static {
        BooleanAdapter booleanAdapter = new BooleanAdapter();
        gson = new GsonBuilder()
            .serializeNulls()
            .disableHtmlEscaping()
            .setLenient()
            .registerTypeAdapter(Boolean.class, booleanAdapter)
            .registerTypeAdapter(boolean.class, booleanAdapter)
            .create();
    }
}

when I test it:

val json = "{\"force\"=\"1\"}"
val info = JsonUtil.fromJsonObject(json, UpdateInfo::class.java)
println(info)
println(info.force == 1)
println(info.isForceUpdate)

I get:

UpdateInfo(description=null, force=1, platform=null, title=null, url=null,versionCode=0)
true
false

What?? info.isForceUpdate = false ???
Then I tried lateinit or by lazy{}, still not works. So, what should I do..I'm useing info.force==1 directly now,but I still want to know why this happend.


Solution

  • The problem is that the property val isForceUpdate = force == 1 is computed once at the instantiation of the class and then stored in a field. Because Gson is using Unsafe to instantiate the class, the field is set to its default value false.

    All you have to do to fix this is change the property to a computed property:

    val isForceUpdate get() = force == 1
    

    so that the value is computed on any call and not stored in a field.