ktoml
ktoml copied to clipboard
Does ktoml support `Map<String, T>` field types?
Hi, I'm trying to deserialize a TOML like this:
[coins.bitcoin]
scale = 8
default_volume = 0.1
skip_in_orderbook = 0.00001
[coins.ethereum]
scale = 8
default_volume = 0.2
skip_in_orderbook = 0.00001
[coins.tether]
scale = 2
default_volume = 100
skip_in_orderbook = 0.0001
Here's my structure:
@Serializable
data class Coin(
val scale: Long,
@SerialName("default_volume")
val defaultVolume: Double,
@SerialName("skip_in_orderbook")
val skipInOrderbook: Double,
)
@Serializable
data class CoinsConf(
val coins: Map<String, Coin>
)
I'm getting this error:
Unexpected exception thrown: com.akuleshov7.ktoml.exceptions.MissingRequiredPropertyException: Invalid number of key-value arguments provided in the input for deserialization. Missing required property <0> from class <kotlin.collections.LinkedHashMap> in the input
Is this a bug, or ktoml doesn't support Map?
For reference, this code in Rust using serde works just fine:
#[derive(Deserialize, Debug)]
pub struct Coin {
pub scale: u32,
pub default_volume: f64,
pub skip_in_orderbook: f64,
}
#[derive(Deserialize, Debug)]
pub struct CoinsConfig {
coins: HashMap<String, Coin>,
}
@antekone hello!
It looks like you are using decoding a little bit incorrectly. In TOML coins.bitcoin is the same to the following table:
[coins]
[coins.bitcoin]
key = value
that should be decided by the following data class:
data class Decoder (val coins: Coins)
data class Coins (val bitcoin: MyType, val etherium: MyType)
data class MyType(val scale: Double)
you can also use generics with data classes
Hi, thanks for quick reply.
When I hardcode the structures like you've suggested, then it works. But I would like the definition to be more dynamic, so when someone adds new "cryptocoins" to the TOML config, the tool won't have to be recompiled.
For example, when I use JSON deserializer, then it works as well:
{
"coins": {
"bitcoin": {
"scale": 8,
"default_volume": 0.1,
"skip_in_orderbook": 0.00001
},
"ethereum": {
"scale": 8,
"default_volume": 0.3,
"skip_in_orderbook": 0.00001
},
"litecoin": {
"scale": 8,
"default_volume": 1,
"skip_in_orderbook": 0.01
},
"tether": {
"scale": 2,
"default_volume": 100,
"skip_in_orderbook": 1
}
}
}
Deserializer:
@Serializable
data class Coin(
val scale: Long,
@SerialName("default_volume")
val defaultVolume: Double,
@SerialName("skip_in_orderbook")
val skipInOrderbook: Double,
)
@Serializable
data class CoinsConf(
val coins: Map<String, Coin>
)
Do you suggest that using Map<String, Coin> here is not a good way to define the serializer? (I admit I don't know TOML that well)
Got it, TOML spec actually should not support flexible dynamic tables (has stable schema). But it should be easy to support it in KTOML, as kotlinx supports that. Let me think about the solution.
@antekone finally fixed in latest 0.5.1 release :)
duplicated by https://github.com/akuleshov7/ktoml/issues/234