If a field can either be a `String` or a `List<...
# serialization
v
If a field can either be a
String
or a
List<String>
in the serialized format, can this somehow be catered for with
kotlinx.serialization
? In my concrete case I try using
kaml
to parse a GitHub workflow yml file. It can for example have this:
Copy code
jobs:
  job1:
  job2:
    needs: job1
  job3:
    needs: [job1, job2]
n
i think the best way would be to have a custom serializer that turns a single item list into a String and the reverse
v
Do you maybe have an eye? To get the grip of a custom serializer I wanted to start with a simple overall case. I also parse a GitHub action yml file. There you can have
Copy code
outputs:
    foo:
        description: bar
        value: baz

runs:
    using: composite
or
Copy code
outputs:
    foo:
        description: bar

runs:
    using: something else
Meaning the output has a mandatory
value
property if it is a composite action but no
value
property if it is a normal action. Previously I didn't support composite, so I had
Copy code
@Serializable
data class GitHubAction(
        /* ... */
        val outputs: Map<String, Output>? = null,
        /* ... */
) {
    /* ... */
    @Serializable
    data class Output(
            val description: String
    )
    /* ... */
}
I now changed it to
Copy code
@Serializable
data class GitHubAction(
        /* ... */
        val outputs: Map<String, Output>? = null,
        /* ... */
) {
    /* ... */
    sealed class Output {
        abstract val description: String

        data class NormalOutput(
                override val description: String
        ) : Output()

        data class CompositeOutput(
                override val description: String,
                val value: String
        ) : Output()

        @Serializer(forClass = Output::class)
        companion object : KSerializer<Output> {
            override val descriptor: SerialDescriptor = SerialDescriptor("net.kautler.dao.GitHubAction.Output", SEALED) {
                element("normal", SerialDescriptor("net.kautler.dao.GitHubAction.Output.NormalOutput") {
                    element("description", PrimitiveDescriptor("net.kautler.dao.GitHubAction.Output.NormalOutput.description", STRING))
                })
                element("composite", SerialDescriptor("net.kautler.dao.GitHubAction.Output.CompositeOutput") {
                    element("description", PrimitiveDescriptor("net.kautler.dao.GitHubAction.Output.CompositeOutput.description", STRING))
                    element("value", PrimitiveDescriptor("net.kautler.dao.GitHubAction.Output.CompositeOutput.value", STRING))
                })
            }

            override fun deserialize(decoder: Decoder): Output {
                TODO("deserialize: Not yet implemented")
            }

            override fun serialize(encoder: Encoder, value: Output) {
                TODO("serialize: Not yet implemented")
            }
        }
    }
    /* ... */
}
Two questions: • does it look correct generally or did I completely got something wrong? • why doesn't it work? The
descriptor
is used, when I had a
TODO()
in there it failed, but then on deserialization there comes an error from kaml complaining about the missing polymorphism type tag in the input so it seems the custom serializer is not used.
n
maye try the
@Serializable(with=Output.Companion::class)
annotation on the outputs property instead to force it
v
The author of kaml said I should use
CONTEXTUAL
instead of
SEALED
. And it seems to indeed help. Is really
CONTEXTUAL
appropriate here, or is it a bug, that kaml does not respect the custom serializer? When should you use
CONTEXTUAL
and when
SEALED
generally? What is the effective difference?
Even forcing the serializer like you suggested did not work, so I guess it indeed is a bug in kaml. But still my question, what are the differences and implications between
CONTEXTUAL
and
SEALED
as
SEALED
is, what the official example uses.
v
For JSON we have `JsonTransformingSerializer`: https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/json.md#json-transformations For kaml a special support from kaml format implementation is required
v
Yep, already requested that, but maintainer does not have that many time for implementing it. But in the meantime I already solved everything using custom serializers. :-)