How to distinguish between
{data: null}
and {}
in kotlinx.serialization when deserializing JSON?
@Serializable
class MyClass(val data: String?)
How to distinguish between
{data: null}
and {}
in kotlinx.serialization when deserializing JSON?
@Serializable
class MyClass(val data: String?)
You need a custom setter and a private boolean field to indicate whether the field value was touched. So something like:
@Serializable
class MyClass {
private var isDataTouched = false
val data: String
set(value) {
field = value
isDataTouched = true
}
}
Note, you can't define the field in the default constructor.
You can take advantage of polymorphism coupled with JsonContentPolymorphicSerializer
to distinguish what type of response you're deserializing:
@Serializable(with = MyResponseSerializer::class)
sealed class MyResponse
@Serializable
class MyEmptyClass : MyResponse()
@Serializable
class MyClass(val data: String?) : MyResponse()
// this serializer is reponsible for determining what class we will receive
// by inspecting json structure
object MyResponseSerializer : JsonContentPolymorphicSerializer<MyResponse>(MyResponse::class) {
override fun selectDeserializer(element: JsonElement) = when {
"data" in element.jsonObject -> MyClass.serializer()
else -> MyEmptyClass.serializer()
}
}
After that deserialize using MyResponse
class and you will receive either MyEmptyClass
or MyClass
:
val e = Json.decodeFromString<MyResponse>("""{}""") // returns MyEmptyClass object
val o = Json.decodeFromString<MyResponse>("""{"data": null}""") // returns MyClass object
println(Json.encodeToString(e)) // {}
println(Json.encodeToString(o)) // {"data": null}
// since sealed class is the parent we can have exhaustive when:
when(e) {
is MyClass -> TODO("handle response with data")
is MyEmptyClass -> TODO("handle empty response")
}