crumpf
03/02/2021, 8:24 PMencodeDefaults
in the Json serialization class so defaults do get encoded. But, this has the side effect of encoding null
into the json for properties that have been given default null values which is not desirable for communicating with some backend systems. So, I was wondering others have settled on for conventions or patterns to deal with this kind of thing. For example, lets considering the following example:
interface MyInterface {
val instruction: String
val requiredField: String
}
@Serializable
data class MyDataClass(
override val requiredField: String,
val optionalField: String? = null
) : MyInterface {
override val instruction: String = "doABarrelRoll"
}
Here, we’ve got MyInterface which describes the basic contract that all messages exchanged with a service should adopt. To see what the effects of encodeDefault
being true/false, the following code
val data = MyDataClass("foo")
println(Json.encodeToString(data))
println(Json { encodeDefaults = true }.encodeToString(data))
would output:
{"requiredField":"foo"}
{"requiredField":"foo","optionalField":null,"instruction":"doABarrelRoll"}
But, we desire:
{
"requiredField": "foo",
"instruction": "doABarrelRoll"
}
I know that a custom Serializer can be written for MyDataClass which could ignore encoding null values for properties. But, this seems that it would need to be done for all classes that incorporate optional properties. Apart from custom Serializers, has anyone used other strategies or structures for being able to encode defaults while ignoring nulls?crumpf
03/02/2021, 8:43 PMinstruction
in this case) and in the implementing class use lateinit and make an assignment in an init block to get the desired output.
interface MyOtherInterface {
var instruction: String
val requiredField: String
}
@Serializable
data class MyOtherDataClass(
override val requiredField: String,
val optionalField: String? = null
) : MyOtherInterface {
override lateinit var instruction: String
init {
instruction = "doAnotherBarrelRoll"
}
}
val data = MyOtherDataClass("bar")
println(Json.encodeToString(data))
outputs:
{
"requiredField": "bar",
"instruction": "doAnotherBarrelRoll"
}
So, I get the json I was hoping for, but this would require losing immutability on the instruction
property and also require the author of each implementing class to know to follow this pattern.pdvrieze
03/03/2021, 9:25 AM@Required
) that you can put on your properties to stop them being omitted if they equal the default. (see https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/basic-serialization.md#transient-properties)crumpf
03/03/2021, 2:14 PM@Required
. Probably because the documentation looks like it only addresses decoding. But, it does appear to work for encoding too. You’re my hero, @pdvrieze