Calculated transient value is null after deserialisation

Hi,

I run into an error which I do not understand after deserializing with gson.
My usecase is way more complex, but I created this test below which shows the behaviour I see.
The issue is the calculated transient value (allObjs) that is null after deserialisation. The unit test fails on the last assert.
Apparently the @Transient prevents correct initialisation of allObjs after deserialisation.

Is this expected behaviour? Can I do anything to make the field work in this way?

If not then I have to convert all the transient fields to functions like getThemAll(), which does work.

I hope for any insights.

Regards, Rob

class CoupleDeserializeTest {

    data class Couple( val objA: String, val objB: String){
        @Transient
        val allObjs: List<String> = listOf(objA, objB)

        fun getThemAll() = listOf(objA, objB)
    }

    @Test
    fun testDe_SerializeCouple() {

        val couple = Couple("my", "text")

        // This succeeds
        Assert.assertNotNull(couple.allObjs)

        val gson = Gson()
        val json = gson.toJson(couple)

        // This succeeds
        Assert.assertEquals("{\"objA\":\"my\",\"objB\":\"text\"}", json)

        val coupleDeserialized = gson.fromJson<Couple>(json, Couple::class.java)

        // This succeeds
        Assert.assertNotNull(coupleDeserialized.getThemAll())

        // This fails
        Assert.assertNotNull(coupleDeserialized.allObjs)
    }
}

It is the expected behavior

That link also tells you how to override that behaviour from Gson.

By the way, why do you need @Transient on that field? Are you using both java serialization and Gson? If so you could drop @Transient and always use Gson.

This is a simplified example of what we have, I added @Transient to avoid serialisation by gson.
And thanks for the guide, I have been using gson for so long that I forgot about exclusion strategies. Not sure If I will go that way.

To understand your answer correct: gson totally circumvents normal initialisation of an instance?

That is because Gson creates instance of Couple with null values (he doesn’t care that Kotlin forbids it :smiley: ) , and after that he sets fields from JSON. You have set up allObjects to have initial values of provided objA, objB … so that initialization captures NULL values.
In this case this can be mitigated by using lazy initialization.

Gson can’t know what were the parameters you passed to the constructor (or which constuctor to call if there are many). It can only know what are the values of the fields of the constructed object.

In your case you can add a getter to allObjs so that also in kotlin reading the field is a method call, like getThemAll is now.