I have a complex JSON file and I'd like to extract only a single value out of it. I could define all of the struct
s and derive Deserialize
on all of them, but I'd like to just write a little manual code to pull that one value out. The Serde documentation, quite frankly, just confused me.
My JSON content has the following layout:
{
"data": [
{
"hostname": "a hostname"
}
]
}
I'm looking for the value navigated to by going into data
, then taking the first element of the array, and taking the value of hostname
.
In Haskell, I'd do it like this:
newtype Host = Host Text
instance FromJSON Host where
parseJSON (Object o) = (return . Host) <=< (.: "hostname") <=< (fmap (!! 0) . parseJSON) <=< (.: "data") $ o
parseJSON _ = mzero
What's the equivalent for Serde?
The serde_json
crate provides types for generic JSON values with 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")