The kotlinx.serialization Json format is able to f...
# serialization
r
The kotlinx.serialization Json format is able to fall back on default values if something is missing during decoding. So if you have a class
Copy code
@Serializable
data class Foo(val bar: String = "bar")
and deserialize an empty json object
Copy code
val foo = Json.decodeFromString(Foo.serializer(), "{}")
then you get
Foo("bar")
as output rather than an error or
Foo("")
or something else. Can anyone point to what makes that happen? I want to do something similar for a custom format. (NB I’m not looking for the
encodeDefaults
option. That flag controls whether default values are added to Json output. I’m looking for how default values are inferred when missing from Json input.)
p
I cannot answer your question definitively without causing serious pain to my brain but I can tell you that
JsonTransformingSerializer
has become my best friend for situations where I need to munge Json to get what I want. Copious examples exist on my LSP for Kotlin (lsp4k-sdk) repo with more being added daily.
d
Fairly certain this is done at compile time. The plugin will copy the default value code and execute it instead of asserting a missing field. Just don't report the field and it should just work.
(In the generated serializers only of course)
r
I’m trying to understand it from the perspective of `Encoder`/`Decoder` rather than
KSerializer
, for the purposes of writing a custom serialization format. For example,
AbstractEncoder
has a method
encodeElement()
where you can return
false
to ignore an element in your encoded output. But I don’t see an equivalent in
AbstractDecoder
to report that something is missing from the input you’re trying to decode.
p
Russell, are you looking to build a custom format that is not Json? If so, I definitely cannot help you but if you are using Json, then I would be willing to pair up with you to get to a solution. As part of creating a Kotlin SDK for the LSP I've been drilling into the KXS a fair bit. As has Bryan at TM. You might want to ping him as well.
r
Yes I’m looking to build a custom format that’s not json. I think I have a way forward by not returning an index from
decodeElementIndex()
if it corresponds to something that’s not present in the data. But I don’t quite have it working yet.
Not sure if it’s confusing out of context, but here’s where I got it working if anyone’s following along https://github.com/russhwolf/multiplatform-settings/commit/faccbaa0746ad705456958dcad6c9c487b06a09d Previously
decodeElementIndex()
would iterate through every index from 0 to
descriptor.elementsCount
. Now, it first checks if
descriptor.isElementOptional(index)
returns true and if the value is missing from the data it’s trying to decode. If so, it iterates to the next index.