Skip to content

Instantly share code, notes, and snippets.

@itarato
Created December 8, 2018 13:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save itarato/a78a04bde14acea8189e65eca01fe953 to your computer and use it in GitHub Desktop.
Save itarato/a78a04bde14acea8189e65eca01fe953 to your computer and use it in GitHub Desktop.
Serde JSON nest digger
use serde_json::Value;
#[derive(Debug)]
enum Shovel {
Key(&'static str),
Index(usize),
}
fn dig(val: Value, with: &[Shovel]) -> Option<Value> {
if with.len() == 0 {
return Some(val);
}
match with[0] {
Shovel::Key(key) => {
match val.as_object() {
Some(dict) => {
match dict.get(key) {
Some(map_val) => dig(map_val.clone(), &with[1..with.len()]),
None => None,
}
},
None => None,
}
},
Shovel::Index(i) => {
match val.as_array() {
Some(arr) => dig(arr[i].clone(), &with[1..with.len()]),
None => None,
}
},
}
}
#[test]
fn test_dig_object() {
let data: Value = serde_json::from_str(r#"{"foo": "bar", "bar": [1, 2, 3]}"#).unwrap();
let res = dig(data, &[Shovel::Key("foo")]);
assert_eq!("bar", res.unwrap().as_str().unwrap());
}
#[test]
fn test_dig_array() {
let data: Value = serde_json::from_str(r#"{"foo": "bar", "bar": [1, 2, 3]}"#).unwrap();
let res = dig(data, &[Shovel::Key("bar"), Shovel::Index(2)]);
assert_eq!(3, res.unwrap().as_i64().unwrap());
}
#[test]
fn test_dig_multiple_times() {
let data: Value = serde_json::from_str(r#"{"foo": "bar", "bar": [1, 2, 3]}"#).unwrap();
let res_data = dig(data.clone(), &[Shovel::Key("foo")]);
let res_index = dig(data.clone(), &[Shovel::Key("bar"), Shovel::Index(2)]);
assert_eq!("bar", res_data.unwrap().as_str().unwrap());
assert_eq!(3, res_index.unwrap().as_i64().unwrap());
}
#[test]
fn dig_no_key() {
let data: Value = serde_json::from_str(r#"{"foo": "bar", "bar": [1, 2, 3]}"#).unwrap();
let res = dig(data, &[Shovel::Key("barbar")]);
assert!(res.is_none());
}
#[test]
fn dig_wrong_type_not_object() {
let data: Value = serde_json::from_str(r#"{"foo": "bar", "bar": [1, 2, 3]}"#).unwrap();
let res = dig(data, &[Shovel::Key("bar"), Shovel::Key("foo")]);
assert!(res.is_none());
}
#[test]
fn dig_wrong_type_not_array() {
let data: Value = serde_json::from_str(r#"{"foo": "bar", "bar": [1, 2, 3]}"#).unwrap();
let res = dig(data, &[Shovel::Index(2), Shovel::Index(1)]);
assert!(res.is_none());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment