/ / Auswahl einer Teilmenge von Schlüsseln aus einem JSON-Array - JSON, Parsing, Rost

Auswählen einer Teilmenge von Schlüsseln aus einem JSON-Array - json, parsing, rost

Ich versuche, eine JSON-API zu analysieren, die Ausgaben wie folgt ausspuckt:

{
"message": "success",
"number": 6,
"people": [
{
"craft": "ISS",
"name": "Gennady Padalka"
},
{
"craft": "ISS",
"name": "Mikhail Kornienko"
},
{
"craft": "ISS",
"name": "Scott Kelly"
},
{
"craft": "ISS",
"name": "Oleg Kononenko"
},
{
"craft": "ISS",
"name": "Kimiya Yui"
},
{
"craft": "ISS",
"name": "Kjell Lindgren"
}
]
}

Quelle: http://api.open-notify.org/astros.json

Ich benutze Serde Dafür und bisher ist es gelungen, den folgenden Code zu erstellen:

extern crate curl;
extern crate serde_json;

use curl::http;
use std::str;
use serde_json::{from_str};

fn main() {
// Fetch the data
let response = http::handle()
.get("http://api.open-notify.org/astros.json")
.exec().unwrap();

// Get the raw utf-8 bytes
let raw_bytes = response.get_body();
// Convert them to a &str
let string_body: &str = str::from_utf8(&raw_bytes).unwrap();

// Get the JSON into a "Value" Rust type
let json: serde_json::Value = serde_json::from_str(&string_body).unwrap();

// Get the number of people in space
let num_of_ppl: i64 = json.find_path(&["number"]).unwrap().as_i64().unwrap();
println!("There are {} people on the ISS at the moment, they are: ", num_of_ppl);

// Get the astronauts
// Returns a "Value" vector of people
let ppl_value_space = json.find_path(&["people"]).unwrap();
println!("{:?}", ppl_value_space);
}

Jetzt, ppl_value_space bringt mir das, wie erwartet:

[{"craft":"ISS","name":"Gennady Padalka"}, {"craft":"ISS","name":"Mikhail Kornienko"}, {"craft":"ISS","name":"Scott Kelly"}, {"craft":"ISS","name":"Oleg Kononenko"}, {"craft":"ISS","name":"Kimiya Yui"}, {"craft":"ISS","name":"Kjell Lindgren"}]

Aber ich möchte zur "name" Schlüssel, um im Wesentlichen etwas wie:

[{"name":"Gennady Padalka"}, {"name":"Mikhail Kornienko"}, {"name":"Scott Kelly"}, {"name":"Oleg Kononenko"}, {"name":"Kimiya Yui"}, {"name":"Kjell Lindgren"}]

Um nur die Namen der Astronauten im Weltraum zu bekommen.

Wie bekomme ich das? "name" innerhalb "people", ohne das "craft"?

ich versucht zu erreichen name so:

ppl_value_space[0].find_path(&["name"]).unwrap();

Aber es endet mit einer Panik, was im Grunde bedeutet, dass der Schlüssel ist None, seit ich unwrap() ein Option<T>.

Antworten:

2 für die Antwort № 1

Das hat für mich funktioniert:

if let &Value::Array(ref people) = ppl_value_space {
let names = people.iter().filter_map(|person| person.find_path(&["name"]));
for name in names {
println!("{:?}", name);
}
}

Seit einem serde_json::Value ist ein enumEs kann viele verschiedene Arten von Werten geben. Und Array ist nur eine davon, es könnte andere Dinge wie eine Zeichenfolge oder eine Zahl sein. Wir erwarten, dass es ein Array ist, aber Rust zwingt uns, über die anderen Fälle nachzudenken.

In diesem Fall ignorieren wir alle Typen außer a Value::Array mit einem wenn-lassen Erklärung. Wenn die Bedingung wahr ist, erhalten wir einen Verweis auf das enthaltene Array.

Wir durchlaufen jedes Element im Array und finden darin das Namensobjekt. filter_map wird verwendet, um zu ignorieren None Werte, aber Sie möchten vielleicht etwas anderes tun.

Jeder Wert wird ausgedruckt, aber Sie könnten auch collect sie in ein neues Vec oder etwas spannenderes.