Home > database >  Trying to loop over JSON keys
Trying to loop over JSON keys

Time:02-10

i have been wondering how to solve the following problem.

you have a JSON like this and you parse using serde.

{
    "student_name": "this guy",
    "subjects": [{"Chemistry": 0},
                {"Politics": 0},
                {"Biology": 0},
                {"Art": 0}],
}

then use a struct to map the types

struct Environment {
    student_name: String,
    subjects: Vec<HashMap<String, i32>>,
}

but when you try to loop over the keys from the subjects Vector you get all kinds of nasty errors like this one

error[E0308]: mismatched types
  --> src/main.rs:15:9
   |
15 |     for (key, val) in json.subjects.iter() {
   |         ^^^^^^^^^^    -------------------- this expression has type std::option::Option<&HashMap<std::string::String, i32>>`
   |         |
   |         expected struct `HashMap`, found tuple
   |
note: expected struct `HashMap<std::string::String, i32>`
               found tuple `(_, _)`

this is all the code, i would really be greatful of someone helping me out. i really lost all hope; thank you beforehand.

use serde_derive::Deserialize;
use serde_json::Result;
use std::{collections::HashMap, fs};

#[derive(Deserialize, Clone)]
struct Environment {
    student_name: String,
    subjects: Vec<HashMap<String, i32>>
}

fn data_parser() -> Result<()> {
    let data = fs::read_to_string("./src/data.json").unwrap();
    let json = serde_json::from_str::<Environment>(&data)?;
    for (key, val) in json.subjects.iter() {
        println!("{}", key);
        println!("----------------------");
    }
    Ok(())
}

fn main() {
    data_parser();
}

CodePudding user response:

You collection is of type Vec<HashMap<String, i32>>, so you are given references to HashMap<String, i32> when iterating, you can flat_map over those as iterators also to actually get what you need:

for (key, val) in json.subjects.iter().flat_map(|d| d.iter()) {
    println!("{}", key);
    println!("----------------------");
}

Playground

CodePudding user response:

A subject is a <HashMap<String, i32>. Try iterating through every subject.

fn data_parser() -> Result<()> {
    let data = fs::read_to_string("./src/data.json").unwrap();
    let json = serde_json::from_str::<Environment>(&data)?;
    for subject in json.subjects.iter() {
        for (_key, value) in subject {
            println!("{}", value);
            println!("----------------------");
        }
    }
    Ok(())
}

Or, better yet, you can "forget" about loops altogether:

 json.subjects
        .iter()
        .flat_map(|s| s.iter())
        .for_each(|(key, value)| {
            println!("{key}: {value}");
            println!("----------------------");
        });
  • Related