-
Notifications
You must be signed in to change notification settings - Fork 664
Description
Hi,
I'm dealing with an annoying JSON service which is out of my control.
If a value is unavailable it is expressed as an empty array [] instead of a canonical absence or null value.
I thought about making a custom JSON deserialiser and manually check if the value was present or not before delegating it to the default generated deserialiser.
However when defining a custom deserialiser it seems the generated deserialiser is not generated no more.
I made a simple test case here:
public object SomeObjSerializer : KSerializer<SomeObj> {
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("SomeObj")
override fun serialize(encoder: Encoder, value: SomeObj) {}
override fun deserialize(decoder: Decoder): SomeObj {
val input = decoder as JsonDecoder
val jsonObj = input.decodeJsonElement().jsonObject
return if (jsonObj["value"] is JsonPrimitive) {
//How to delegate to the default generated serializer?
} else {
SomeObj(null)
}
}
}
@Serializable(with = SomeObjSerializer::class)
public data class SomeObj(val value: String?)
public fun main() {
//language=JSON
val someJson = """{"value" : [] }"""
val clazz = Json.decodeFromString<SomeObj>(someJson)
//language=JSON
val someOtherJson = """{"value" : "42" }"""
val clazz2 = Json.decodeFromString<SomeObj>(someOtherJson)
}Note that this example is a simple use case.
As a temporary solution I made a copy of my object without specifying the custom deserialiser which I reference in my own deserialiser and then map back to my original object.
However that of course does not seem to be a good solution.
public object SomeObjSerializer : KSerializer<SomeObj> {
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("SomeObj")
override fun serialize(encoder: Encoder, value: SomeObj) {}
override fun deserialize(decoder: Decoder): SomeObj {
val input = decoder as JsonDecoder
val jsonObj = input.decodeJsonElement().jsonObject
return if (jsonObj["value"] is JsonPrimitive) {
val obj = decoder.decodeSerializableValue(CopyOfSomeObjForDelegationPurposedOnly.serializer())
SomeObj(obj.value)
} else {
SomeObj(null)
}
}
}
@Serializable(with = SomeObjSerializer::class)
public data class SomeObj(val value: String?)
@Serializable
public data class CopyOfSomeObjForDelegationPurposedOnly(val value: String)
public fun main() {
//language=JSON
val someJson = """{"value" : [] }"""
val clazz = Json.decodeFromString<SomeObj>(someJson)
//language=JSON
val someOtherJson = """{"value" : "42" }"""
val clazz2 = Json.decodeFromString<SomeObj>(someOtherJson)
}