I have a data stream of JSON where some JSON objects may be missing certain fields or have fields I am unaware of in advance.
My solution is to use:
let v: Value = serde_json::from_str(data)?;
How do I handle accessing the field stuff? If I know it exists, I can use:
v["stuff"]
How do I handle the case stuff isn't a field in my data?
My solution is to use [
serde_json::Value]
I'd still use type-driven serialization, wrapping the potentially-missing field in an Option.
use serde::Deserialize; // 1.0.101
use serde_json; // 1.0.40
#[derive(Debug, Deserialize)]
struct Data {
required: i32,
missing: Option<String>,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let data = r#"{"required": 42, "extra": true}"#;
let data = serde_json::from_str::<Data>(data)?;
println!("{:?}", data);
let data = r#"{"required": 42, "extra": true, "missing": "cow"}"#;
let data = serde_json::from_str::<Data>(data)?;
println!("{:?}", data);
Ok(())
}
Data { required: 42, missing: None }
Data { required: 42, missing: Some("cow") }
If you have fields where the name cannot be known at compile time, you can use serde_json::Value in addition to this solution. See How can I use Serde's custom (de)serialization to update a subset of arbitrary input?
See also:
Accessing a missing field by the Index implementation of Value (i.e. v["stuff"]) will panic if the field does not exist. Instead, use Value::get, which returns an Option:
if let Some(field) = v.get("stuff") {
println!("field = {:?}", field);
} else {
println!("field is missing");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With