Is there any way to have this: `{ "foo": "" }` be ...
# serialization
d
Is there any way to have this:
{ "foo": "" }
be null in this:
data class Foo(value: Int? = null)
? (It's supposed to be a number when not an empty string...)
a
the quickest way is probably to use
JsonPrimitive
and the expose the actual value as a property
Copy code
data class Foo(
  private val value: JsonPrimitive? = null
) {
  val actualValue = value?.myConverterFunction()
}
d
Thanks, that's a great idea!
e
or you can hide that behind a surrogate
Copy code
@Serializable(with = Foo.Serializer::class)
data class Foo(val value: Int? = null) {
    @Serializable
    data class Surrogate(val value: JsonPrimitive = JsonNull)
    object Serializer : KSerializer<Foo> {
        override val descriptor: SerialDescriptor = SerialDescriptor("Foo", Surrogate.serializer().descriptor)
        override fun serialize(encoder: Encoder, value: Foo) {
            val surrogate = Surrogate(value = JsonPrimitive(value.value))
            encoder.encodeSerializableValue(Surrogate.serializer(), value)
        }
        override fun deserialize(decoder: Decoder): Foo {
            val surrogate = decoder.decodeSerializableValue(Surrogate.serializer())
            return Foo(value = surrogate.value.intOrNull)
        }
    }
}
d
Interesting too... the only thing is that I have a bunch more fields in that class in reality. It would have been nice to be able to only apply the serializer to that one "non-standard" property and leave the rest alone.
a
you could use a value class to encapsulate some of the logic
Copy code
@Serializable
value class IntConverter(private val value: JsonPrimitive) {
  val actual get() = { value.myConverter... }
}
Then you can re-use the same class in your data class
Copy code
data class Foo(
  private val value: IntConverter? = null
)
e
I don't like that idea much; it'll make
Foo(value = IntConverter(JsonPrimitive("0"))) != Foo(value = IntConverter(JsonPrimitive("-0")))
even though you would want to consider them the same value
a
good point