Read JSON: Warn on extra (unknown) fields with serde_ignored
-
If the
deny_unknown_fields
seems to be too strict, you can use theserde_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" }