Reputation: 35
I am trying to iterate over a hashmap which I have extracted from a serde_json::value::Value
I want to check if the value of a particular key "type" is either "release" or "snapshot".
I did this once in Nodejs, I am trying to replicate this in rust.
Nodejs code for reference purpose:
Json file which I am using:
https://launchermeta.mojang.com/mc/game/version_manifest.json
Here's the piece of code relevant to the question (which I did so far)
requests::file_downloader::async_download_file("https://launchermeta.mojang.com/mc/game/version_manifest.json", &version_json_dir).expect("Error fetching data!");
let f1 = fs::read_to_string(format!("{}/version_manifest.json", version_json_dir)).expect("Error opening file!");
let json_value: serde_json::value::Value = serde_json::from_str(f1.as_str())?;
for (key, value) in json_value["versions"].as_object().unwrap() {
println!("{} => {}", key,value)
}
In another code file I tried this :
let mut h1: HashMap<String,String> = HashMap::new();
h1.insert("id".to_string(),"22w43a".to_string());
h1.insert("type".to_string(), "snapshot".to_string());
println!("{:#?}", h1.get_key_value("type").unwrap().1);
This returns "snapshot" as expected. But my problem is that the json file I am using is huge and I cannot find an effecient way to iterate over the extracted hashmap and implement the above logic.
Upvotes: 0
Views: 660
Reputation: 761
While it can be done using serde_json::Value, it is going to be a pain because you have to check manually everytime whethere a certain value exists, a better way and more rusty way to do it it is the following:
#[derive(Deserialize)]
pub struct Version {
id: String,
url: String,
#[serde(rename="type")]
type_: String,
}
#[derive(Deserialize)]
pub struct MojangResponse {
versions: Vec<Version>,
}
requests::file_downloader::async_download_file("https://launchermeta.mojang.com/mc/game/version_manifest.json", &version_json_dir).expect("Error fetching data!");
let f1 = fs::read_to_string(format!("{}/version_manifest.json", version_json_dir)).expect("Error opening file!");
let json_value: MojangResponse = serde_json::from_str(f1.as_str())?;
for version in json_value.versions.into_iter().filter(|it|&it.type_ == "release") {
println!("{} => {}", version.id,version.url)
}
Notice I used .into_iter()
and not .iter()
which consumes the response but avoids using clone.
Upvotes: 1