Is there a way to omit specially formatted keys in strict mode deserialization? #595
-
I am working with format that allows specially-formatted arbitrary keys. Given the following model @Serializable
data class Sample(
val key: String,
val key2: String,
) I can have the following YAML that should be deserialized correctly in my case sample:
key: value
key2: value
-omit-me: true
-and-me: "definitely"
-this-could-be-any-key: true In this example I'd like to be able to use strict mode to automatically verify all mandatory keys ( As of now I'm getting exceptions like this (redacted from original to match sample):
Is there a way to do so? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
This is currently not possible unfortunately. |
Beta Was this translation helpful? Give feedback.
-
@charleskorn thanks for your answer, I appreciate that! I've found a simple workaround that works for me. Not that effective, but better than nothing. Since parsing and deserialization can be done separately, we can simply omit unneeded keys after parsing and before deserealization like this: val parsed = Yaml.default.parseToYamlNode(yaml).dropKeys { it.content.startsWith("-") }
val result = parsed.decode<Root>() With a simple function like this: fun YamlNode.dropKeys(
predicate: (YamlScalar) -> Boolean,
): YamlNode = when (this) {
is YamlMap -> copy(
entries = entries.filterKeys {
!predicate(it)
}.mapValues {
it.value.dropKeys(predicate)
}
)
is YamlList -> copy(
items = items.map {
it.dropKeys(predicate)
}
)
is YamlNull,
is YamlScalar,
is YamlTaggedNode -> this
} And complete example hereinternal class TestKeys {
@Test
fun `fails decode unknown keys`() {
assertFails { Yaml.default.decodeFromString<Root>(yaml) }
}
@Test
fun `omits keys and decodes correctly`() {
val parsed = Yaml.default.parseToYamlNode(yaml).dropKeys { it.content.startsWith("-") }
val expected = Root(
sample = Sample(
key = "value",
nested = Nested(
title = "nested",
nested2 = listOf(Nested2(id = "nested2"))
)
)
)
val result = parsed.decode<Root>()
assertEquals(expected, result)
}
companion object {
val yaml = """
sample:
key: value
-omit-me: true
nested:
title: nested
-omit me too: true
nested2:
- id: nested2
-and me: asd
""".trimIndent()
}
}
@Serializable
data class Root(
val sample: Sample,
)
@Serializable
data class Sample(
val key: String,
val nested: Nested,
)
@Serializable
data class Nested(
val title: String,
val nested2: List<Nested2>,
)
@Serializable
data class Nested2(
val id: String,
) |
Beta Was this translation helpful? Give feedback.
@charleskorn thanks for your answer, I appreciate that!
I've found a simple workaround that works for me. Not that effective, but better than nothing.
Since parsing and deserialization can be done separately, we can simply omit unneeded keys after parsing and before deserealization like this:
With a simple function like this: