notion_into_sqlite/
json_util.rs

1use serde_json::Value;
2
3#[derive(Debug)]
4pub enum JsonKey<'a> {
5    String(&'a str),
6    Index(usize),
7}
8impl<'a> From<&'a str> for JsonKey<'a> {
9    fn from(s: &'a str) -> Self {
10        JsonKey::String(s)
11    }
12}
13impl From<usize> for JsonKey<'_> {
14    fn from(i: usize) -> Self {
15        JsonKey::Index(i)
16    }
17}
18
19pub fn dig_json<'a>(source: &'a Value, keys: &[JsonKey]) -> Option<&'a Value> {
20    let mut value = source;
21    for key in keys {
22        value = match *key {
23            JsonKey::String(k) => value.as_object()?.get(k)?,
24            JsonKey::Index(index) => value.as_array()?.get(index)?,
25        }
26    }
27    Some(value)
28}
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33
34    #[test]
35    fn test_dig_json() {
36        let data = serde_json::from_str::<Value>("{}").unwrap();
37        let keys: Vec<JsonKey> = vec!["foo".into(), "foo".into(), 1.into()];
38        assert!(dig_json(&data, &keys).is_none());
39
40        let data = serde_json::from_str::<Value>(
41            r#"{
42            "foo": {
43                "bar": [
44                    {
45                        "id": "xxx"
46                    }
47                ]
48            }
49        }"#,
50        )
51        .unwrap();
52        let keys: Vec<JsonKey> = vec!["foo".into(), "bar".into(), 0.into(), "id".into()];
53        assert_eq!(dig_json(&data, &keys).unwrap(), "xxx");
54    }
55}