bruce_wayne224
bruce_wayne224

Reputation: 35

How to get the particular value of a key from a hashmap while iterating through it, in rust?

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: Nodejs code

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

Answers (1)

Oussama Gammoudi
Oussama Gammoudi

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

Related Questions