config-rs
config-rs copied to clipboard
How to merge sources with existing default values?
Suppose I have this config struct
#[derive(Debug, Deserialize)]
struct MyConfig {
// ...
}
impl Default for MyConfig {
fn default() -> MyConfig {
// some complex logic
}
}
I want to produce a MyConfig, where values explicitly set in config.toml are used, otherwise, the default implementation is used.
Something like
Config::builder().
.add_source(File::with_name("config.toml"))
.set_default(???, MyConfig::default())
.build()?;
But I couldn't figure out a way to do this. This seems like a very common use case, so I feel like I'm missing something.
Does the following work
#[derive(Debug, Deserialize)]
+#[serde(default)]
struct MyConfig {
// ...
}
impl Default for MyConfig {
fn default() -> MyConfig {
// some complex logic
}
}
See https://serde.rs/container-attrs.html#default
I achieved it with the following pattern:
let defaults = Config::try_from(&MyConfig::default())?;
Config::builder()
.add_source(defaults)
.add_source(config::File::with_name("config.toml"))
.build()?
You just need to derive Serialize on MyConfig.
For those wondering, you can also apply #[serde(default = "default_addr")] on individual fields of the struct