Read JSON: Warn on extra (unknown) fields with serde_ignored

  • If the deny_unknown_fields seems to be too strict, you can use the serde_ignored crate to collect the extra fields and do something with that knowledge. For example, to warn about them.

  • Here are two JSON files, a good one with 2 fields and a bad one with an extra field.

{
    "name": "Foo Bar",
    "email": "foo@bar.com"
}
{
    "name": "Foo Bar",
    "email": "foo@bar.com",
    "age": 42
}

We defined the struct to be Deserialize-d just as we did earlier, but then we set up a deserializer and use that to deserialized the JSON string. We now have the list of all the extra fields.

use std::collections::HashSet;

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
struct Person {
    name: String,
    email: String,
}

fn main() {
    let args = std::env::args().collect::<Vec<_>>();
    if args.len() != 2 {
        eprintln!("Usage: {} <json_file>", args[0]);
        std::process::exit(1);
    }
    let json_file = &args[1];
    let content = std::fs::read_to_string(json_file).expect("Unable to read file");
    let person = serde_json::from_str::<Person>(&content).expect("Unable to parse JSON");
    println!("{:?}", person);
    println!("-------");


    let json_deserializer = &mut serde_json::Deserializer::from_str(&content);
    let mut unused = HashSet::new();
    let person: Person = serde_ignored::deserialize(json_deserializer, |path| {
        unused.insert(path.to_string());
    })
    .expect("Unable to parse JSON");

    println!("Unused fields: {:?}", unused);

    println!("{:?}", person);
}
[package]
name = "warn-on-extra-fields"
version = "0.1.0"
edition = "2024"

[dependencies]
serde = { version = "1.0.219", features = ["derive"] }
serde_ignored = "0.1.11"
serde_json = "1.0.140"
$ cargo run good.json
Person { name: "Foo Bar", email: "foo@bar.com" }
-------
Unused fields: {}
Person { name: "Foo Bar", email: "foo@bar.com" }
$ cargo run bad.json
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/warn-on-extra-fields bad.json`
Person { name: "Foo Bar", email: "foo@bar.com" }
-------
Unused fields: {"age"}
Person { name: "Foo Bar", email: "foo@bar.com" }