Home
| Colors: |
May 2025

Accessing JSON Data with Unknown Keys In Rust

Introduction

These are just snippets for now. The most recent is at the top.

use anyhow::Result;
use anyhow::anyhow;
use dirs::home_dir;
use serde_json::Value;
use std::fs;
use std::path::PathBuf;

fn main() -> Result<()> {
  extract_cards()
}

fn extract_card(card: &Value) -> Result<()> {
  let card_name = get_card_name(card)?;
  dbg!(card_name);
  Ok(())
}

fn extract_cards() -> Result<()> {
  let input_data = load_json()?;
  input_data
    .as_object()
    .ok_or(anyhow!("Could not load cards object"))?
    .get_key_value("cards")
    .ok_or(anyhow!("Could not get cards"))?
    .1
    .as_array()
    .ok_or(anyhow!("Could not get cards array"))?
    .iter()
    .for_each(|card| {
      let _ = extract_card(card);
    });
  Ok(())
}

fn get_card_name(card: &Value) -> Result<String> {
  Ok(
    card
      .as_object()
      .ok_or(anyhow!("Could not get card as object"))?
      .get_key_value("name")
      .ok_or(anyhow!("Could not get name"))?
      .1
      .to_string(),
  )
}

fn json_path() -> PathBuf {
  home_dir()
    .unwrap()
    .join("workshop")
    .join("mtg-data")
    .join("scryfall")
    .join("current")
    .join("oracle-cards--sample.json")
}

fn load_json() -> Result<Value> {
  println!("Loading JSON...");
  let raw_input = fs::read_to_string(json_path()).unwrap();
  let wrapped_input = format!(r#"{{ "cards": {} }}"#, raw_input);
  let data = serde_json::from_str(wrapped_input.as_str())?;
  println!("Finished Loading JSON...");
  Ok(data)
}

Prior Examples

impl Book {
    pub fn get_words_of_kind(&self, kind: &str) -> Result<Vec<String>> {
        Ok(self.letters[0].words
            .as_object()
            .expect("asdf")
            .values()
            .filter_map(|x| {
                match x["meanings"].as_array() {
                    Some(meanings) => { 
                        meanings.iter().take(1).find_map(|meaning| {
                            match meaning["speech_part"].as_str() {
                                Some(speech_part) => {
                                    if kind == speech_part {
                                        Some(x["word"].as_str()?.to_string())
                                    } else {
                                        None
                                    }
                                },
                                None => None
                            }
                        })
                    }
                    None => None
                }
            }).collect()
        )
    }
}
---
[dependencies]
anyhow = "1.0.98"
serde_json = "1.0.140"
---

use anyhow::Result;
use std::path::PathBuf;
use std::fs;
use serde_json::{Value};

struct Book {
    letters: Vec<Letter>
}

struct Letter {
    words: Value
}

impl Book {
    pub fn word_data(&self) -> Result<Vec<&Value>> {
        let x: &Vec<&Value> = &self.letters[0].words.as_object().expect("asdf").values().map(|x| x).collect();
        dbg!(x);
        Ok(vec![])
    }
}

fn main() -> Result<()> {
    let book = load_data()?;
    book.word_data()?;
    //dbg!(book?.adjectives()?.len());
    Ok(())
}



pub fn load_data() -> Result<Book> {
    let files = get_files_in_dir(&PathBuf::from("data-letters"))?;
    let book = Book {letters: files.iter().map(|f| {
        let content = fs::read_to_string(f).unwrap();
        let letter = 
            Letter{
            words: serde_json::from_str(&content).unwrap()
            };
        letter
    }).collect()};
    Ok(book)
}



pub fn get_files_in_dir(dir: &PathBuf) -> Result<Vec<PathBuf>> {
    let files = fs::read_dir(dir)?
        .into_iter()
        .filter(|p| {
            if p.as_ref().unwrap().path().is_file() {
                true
            } else {
                false
            }
        })
        .map(|p| p.as_ref().unwrap().path())
        .filter(|p| {
            !p.file_name().unwrap().to_str().unwrap().starts_with(".")
        })
        .collect();
    Ok(files)
}


let x = &self.letters[0].words.as_object().expect("asdf").values().for_each(|x| {dbg!(x); ()});
end of line