orchestr7 / ktoml

Kotlin Multiplatform parser and compile-time serializer/deserializer for TOML format (Native, JS, JVM) based on KxS
https://akuleshov7.github.io/ktoml
MIT License
448 stars 23 forks source link

Support unknown table keys #97

Open JakeWharton opened 2 years ago

JakeWharton commented 2 years ago

Give a TOML like:

[known]
foo = "bar"

[known.unknownA]
blah = "one"

[known.unknownB]
blah = "two"

I don't see a way to bind this while also still doing type validation on the known table and the unknown child table shapes (just not their keys).

I would want to bind it against a type defined something like this:

@Serializable
data class Config(
  val known: Known,
  @UnboundTables // Probably needs some marker annotation like this?
  val unknowns: Map<String, KnownChild>,
)
@Serializable
data class Known(val foo: String)
@Serializable
data class KnownChild(val blah: String)

In the case where the child tables do not conform to the same shape, this should also be allowed:

@Serializable
data class Config(
  val known: Known,
  @UnboundTables // Probably needs some marker annotation like this?
  val unknowns: Map<String, TomlTable>,
)
@Serializable
data class Known(val foo: String)

And finally, I have a real-world case which is mixing known table names and unknown table names in a single type. So the TOML looks like this:

[knownA]
foo = "bar"

[knownB]
foo = "baz"

[unknownA]
thing = "something"
other = "whatever"

[unknownB]
thing = "it's a thing"
other = "stuff"

Ideally I could somehow bind this against a type like:

@Serializable
data class Config(
  val knownA: Known,
  val knownB: Known,
  @UnboundTables // Probably needs some marker annotation like this?
  val unknowns: Map<String, Other>,
)
@Serializable
data class Known(val foo: String)
@Serializable
data class Other(val thing: String, val other: String)

I looked through the issues, documentation, and tests cases and didn't see anything that would suggest this is supported today. So far the only path forward I've seen is to go directly to TomlTable and do the entirety of the type binding myself.

orchestr7 commented 2 years ago

@JakeWharton we already have a configuration property, that can skip all unknown keys:

Toml(
    ktomlConf = KtomlConf(
        // allow/prohibit unknown names during the deserialization, default false
        ignoreUnknownNames = false,
    )
)

https://github.com/akuleshov7/ktoml#configuration

Or you won't like to skip them? You would like to process unknown tables that are not mentioned in a schema somehow?

orchestr7 commented 2 years ago

You think that we need to put all unknown tables into some map, that has a String key? That is a little bit unusual for TOML specification... But I love the idea.

That is definitely an enhancement, that should be done under a separate configuration as it breaks TOML standard

SaTae66 commented 2 years ago

Any progress on this so far?