18

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?

0

2 Answers 2

28

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:

Sign up to request clarification or add additional context in comments.

Comments

19

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");
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.