Skip to content

bug: Using the serde attribute rename fails since 0.14.0 with a missing field error #522

@gabrielkim13

Description

@gabrielkim13

Starting at [email protected], serde renamed fields are no longer supported due to the "missing field" error.


Consider the following minimal reproduceable example:

# Cargo.toml

[package]
name = "config-missing-field"
version = "0.1.0"
edition = "2021"

[dependencies]
config = { version = "0.14", default-features = false, features = ["json"] }
serde = { version = "1", features = ["derive"] }
// main.rs

use config::{Config, File, FileFormat};

#[allow(unused)]
#[derive(serde::Deserialize, Debug)]
struct MyConfig {
    #[serde(rename = "FooBar")]
    foo_bar: String,
}

fn main() {
    const MY_CONFIG: &str = r#"{
        "FooBar": "Hello, world!"
    }"#;

    let cfg = Config::builder()
        .add_source(File::from_str(MY_CONFIG, FileFormat::Json))
        .build()
        .unwrap();

    println!("{cfg:#?}");

    let my_config: MyConfig = cfg.try_deserialize().unwrap();

    // Panics at the previous instruction, with "missing field" error.

    println!("{my_config:#?}");
}

The output is as follows:

❯ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
     Running `target/debug/config-missing-field`
Config {
    defaults: {},
    overrides: {},
    sources: [],
    cache: Value {
        origin: None,
        kind: Table(
            {
                "foobar": Value {
                    origin: None,
                    kind: String(
                        "Hello, world!",
                    ),
                },
            },
        ),
    },
}
thread 'main' panicked at src/main.rs:27:53:
called `Result::unwrap()` on an `Err` value: missing field `FooBar`
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace 

Reverting the dependency back to [email protected] works as expected:

❯ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
     Running `target/debug/config-missing-field`
Config {
    defaults: {},
    overrides: {},
    sources: [],
    cache: Value {
        origin: None,
        kind: Table(
            {
                "FooBar": Value {
                    origin: None,
                    kind: String(
                        "Hello, world!",
                    ),
                },
            },
        ),
    },
}
MyConfig {
    foo_bar: "Hello, world!",
} 

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions