如何在不派生结构的情况下使用 serde_json 获取 JSON 文件中的一个特定项目?
How to get at one particular item in JSON file using serde_json without deriving structs?
我有一个复杂的 JSON 文件,我只想从中提取一个值。我可以定义所有 struct
并在所有这些上派生 Deserialize
,但我只想编写一些手动代码来提取那个值。 Serde documentation,老实说,让我很困惑。
我的 JSON 内容具有以下布局:
{
"data": [
{
"hostname": "a hostname"
}
]
}
我正在寻找通过进入 data
导航到的值,然后获取数组的第一个元素,并获取 hostname
的值。
在Haskell中,我会这样做:
newtype Host = Host Text
instance FromJSON Host where
parseJSON (Object o) = (return . Host) <=< (.: "hostname") <=< (fmap (!! 0) . parseJSON) <=< (.: "data") $ o
parseJSON _ = mzero
Serde 的等价物是什么?
serde_json
为泛型 JSON 值提供类型 serde_json::Value
:
use serde_json::Value;
// input variable
let input: &str = "{...}";
// parse into generic JSON value
let root: Value = serde_json::from_str(input)?;
// access element using .get()
let hostname: Option<&str> = root.get("data")
.and_then(|value| value.get(0))
.and_then(|value| value.get("hostname"))
.and_then(|value| value.as_str());
// hostname is Some(string_value) if .data[0].hostname is a string,
// and None if it was not found
println!("hostname = {:?}", hostname); // = Some("a hostname")
use serde::{Serialize, Deserialize};
use serde_json::Value;
#[derive(Serialize, Deserialize)]
struct Payload {
data: Vec<Data>,
#[serde(flatten)]
_: HashMap<String, Value>,
}
#[derive(Serialize, Deserialize)]
struct Data {
hostname: String,
#[serde(flatten)]
_: HashMap<String, Value>,
}
let payload: Payload = serde_json::from_str(your_string)?;
assert_eq!(payload.data.0.hostname, "a hostname");
如果你想在值丢失或格式错误时恐慌,我会使用 the Index
syntax ([...]
). If you want to handle the missing / malformed case, use the get
方法:
fn main() {
let json_value = serde_json::json!({
"data": [
{
"hostname": "a hostname"
}
]
});
let host = &json_value["data"][0]["hostname"];
println!("Host: {:?}", host);
}
您也可以使用 JSON Pointer via pointer
:
let host = json_value.pointer("/data/0/hostname");
println!("Host: {:?}", host);
我有一个复杂的 JSON 文件,我只想从中提取一个值。我可以定义所有 struct
并在所有这些上派生 Deserialize
,但我只想编写一些手动代码来提取那个值。 Serde documentation,老实说,让我很困惑。
我的 JSON 内容具有以下布局:
{
"data": [
{
"hostname": "a hostname"
}
]
}
我正在寻找通过进入 data
导航到的值,然后获取数组的第一个元素,并获取 hostname
的值。
在Haskell中,我会这样做:
newtype Host = Host Text
instance FromJSON Host where
parseJSON (Object o) = (return . Host) <=< (.: "hostname") <=< (fmap (!! 0) . parseJSON) <=< (.: "data") $ o
parseJSON _ = mzero
Serde 的等价物是什么?
serde_json
为泛型 JSON 值提供类型 serde_json::Value
:
use serde_json::Value;
// input variable
let input: &str = "{...}";
// parse into generic JSON value
let root: Value = serde_json::from_str(input)?;
// access element using .get()
let hostname: Option<&str> = root.get("data")
.and_then(|value| value.get(0))
.and_then(|value| value.get("hostname"))
.and_then(|value| value.as_str());
// hostname is Some(string_value) if .data[0].hostname is a string,
// and None if it was not found
println!("hostname = {:?}", hostname); // = Some("a hostname")
use serde::{Serialize, Deserialize};
use serde_json::Value;
#[derive(Serialize, Deserialize)]
struct Payload {
data: Vec<Data>,
#[serde(flatten)]
_: HashMap<String, Value>,
}
#[derive(Serialize, Deserialize)]
struct Data {
hostname: String,
#[serde(flatten)]
_: HashMap<String, Value>,
}
let payload: Payload = serde_json::from_str(your_string)?;
assert_eq!(payload.data.0.hostname, "a hostname");
如果你想在值丢失或格式错误时恐慌,我会使用 the Index
syntax ([...]
). If you want to handle the missing / malformed case, use the get
方法:
fn main() {
let json_value = serde_json::json!({
"data": [
{
"hostname": "a hostname"
}
]
});
let host = &json_value["data"][0]["hostname"];
println!("Host: {:?}", host);
}
您也可以使用 JSON Pointer via pointer
:
let host = json_value.pointer("/data/0/hostname");
println!("Host: {:?}", host);