从 JSON 数组中选择键的子集
Selecting a subset of keys from a JSON array
我正在尝试解析 JSON API 输出如下:
{
"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"
}
]
}
来源:http://api.open-notify.org/astros.json
我正在为此使用 serde 并且到目前为止已经设法提出以下代码:
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);
}
现在,ppl_value_space
得到了我预期的结果:
[{"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"}]
但是,我想找到 "name"
键,本质上是这样的:
[{"name":"Gennady Padalka"}, {"name":"Mikhail Kornienko"}, {"name":"Scott Kelly"}, {"name":"Oleg Kononenko"}, {"name":"Kimiya Yui"}, {"name":"Kjell Lindgren"}]
这样就可以只得到当前在space中的宇航员的名字。
如何在没有 "craft"
的情况下在 "people"
内获得 "name"
?
我 试过 像这样到达 name
:
ppl_value_space[0].find_path(&["name"]).unwrap();
但它以恐慌结束,这基本上意味着密钥是 None
,因为我 unwrap()
一个 Option<T>
.
这对我有用:
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);
}
}
由于 serde_json::Value
是 enum
,它可以是许多不同类型的值。数组只是其中之一,它可以是其他东西,比如字符串或数字。我们希望它是一个数组,但 Rust 迫使我们考虑其他情况。
在这种情况下,我们通过使用 if-let 语句忽略除 Value::Array
之外的所有类型。当条件为真时,我们将获得对包含数组的引用。
我们遍历数组中的每个项目并在其中找到名称对象。 filter_map
用于忽略 None
值,但您可能想做一些不同的事情。
每个值都已打印出来,但您也可以 collect
将它们变成一个新的 Vec
或更令人兴奋的东西。
我正在尝试解析 JSON API 输出如下:
{
"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"
}
]
}
来源:http://api.open-notify.org/astros.json
我正在为此使用 serde 并且到目前为止已经设法提出以下代码:
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);
}
现在,ppl_value_space
得到了我预期的结果:
[{"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"}]
但是,我想找到 "name"
键,本质上是这样的:
[{"name":"Gennady Padalka"}, {"name":"Mikhail Kornienko"}, {"name":"Scott Kelly"}, {"name":"Oleg Kononenko"}, {"name":"Kimiya Yui"}, {"name":"Kjell Lindgren"}]
这样就可以只得到当前在space中的宇航员的名字。
如何在没有 "craft"
的情况下在 "people"
内获得 "name"
?
我 试过 像这样到达 name
:
ppl_value_space[0].find_path(&["name"]).unwrap();
但它以恐慌结束,这基本上意味着密钥是 None
,因为我 unwrap()
一个 Option<T>
.
这对我有用:
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);
}
}
由于 serde_json::Value
是 enum
,它可以是许多不同类型的值。数组只是其中之一,它可以是其他东西,比如字符串或数字。我们希望它是一个数组,但 Rust 迫使我们考虑其他情况。
在这种情况下,我们通过使用 if-let 语句忽略除 Value::Array
之外的所有类型。当条件为真时,我们将获得对包含数组的引用。
我们遍历数组中的每个项目并在其中找到名称对象。 filter_map
用于忽略 None
值,但您可能想做一些不同的事情。
每个值都已打印出来,但您也可以 collect
将它们变成一个新的 Vec
或更令人兴奋的东西。