Как обработать потенциально пропущенные поля, используя serde_json и перечисление Value? - PullRequest
1 голос
/ 23 сентября 2019

У меня есть поток данных JSON, в некоторых объектах JSON могут отсутствовать определенные поля или есть поля, о которых я заранее не знаю.

Мое решение - использовать:

let v: Value = serde_json::from_str(data)?;

Как мне обработать доступ к полю stuff?Если я знаю, что он существует, я могу использовать:

v["stuff"]

Как мне справиться со случаем stuff - это не поле в моих данных?

Ответы [ 2 ]

7 голосов
/ 23 сентября 2019

Доступ к отсутствующему полю с помощью Index реализации Value (то есть v["stuff"]) вызовет панику, если поле не существует.Вместо этого используйте Value::get, который возвращает Option:

if let Some(field) = v.get("stuff") {
    println!("field = {:?}", field);
} else {
    println!("field is missing");
}
2 голосов
/ 23 сентября 2019

Мое решение состоит в том, чтобы использовать [serde_json::Value]

Я бы все еще использовал сериализацию на основе типов, заключая потенциально отсутствующее поле в 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") }

Если у вас есть поля, в которых имя не может быть известно во время компиляции, вы можете использовать serde_json::Value в дополнение к этому решению.См. Как использовать настраиваемую (де) сериализацию Serde для обновления подмножества произвольного ввода?

См. Также:

...