serde_filter/
ignore.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashSet;
3
4#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
5pub struct Ignore {
6    keys: Vec<String>,
7    values: Option<Vec<serde_json::Value>>,
8}
9
10impl Ignore {
11    pub fn new(keys: Vec<&str>) -> Self {
12        let keys = keys.into_iter().map(|s| s.to_string()).collect();
13        Self { keys, values: None }
14    }
15    pub fn sift(json: &serde_json::Value, ignore_keys: &HashSet<String>) -> serde_json::Value {
16        match json {
17            serde_json::Value::Null => json.clone(),
18            serde_json::Value::Bool(_) => json.clone(),
19            serde_json::Value::Number(_) => json.clone(),
20            serde_json::Value::String(_) => json.clone(),
21            serde_json::Value::Array(arr) => {
22                let filtered_arr: Vec<serde_json::Value> = arr
23                    .iter()
24                    .map(|v| Self::sift(v, ignore_keys))
25                    .filter(|v| !v.is_null())
26                    .collect();
27                serde_json::Value::Array(filtered_arr)
28            }
29            serde_json::Value::Object(map) => {
30                let filtered_map: serde_json::Map<String, serde_json::Value> = map
31                    .iter()
32                    .filter(|(k, _)| !&ignore_keys.contains(k.as_str()))
33                    .map(|(k, v)| (k.clone(), Self::sift(v, ignore_keys)))
34                    .filter(|(_, v)| !v.is_null())
35                    .collect();
36                serde_json::Value::Object(filtered_map)
37            }
38        }
39    }
40}
41
42impl super::filter::Filter for Ignore {
43    type Output = serde_json::Value;
44    fn filter(&self, json: serde_json::Value) -> Result<Self::Output, anyhow::Error> {
45        let ignore_k = self.keys.clone();
46        let filtered = Ignore::sift(&json, &ignore_k.into_iter().collect());
47        Ok(filtered)
48    }
49}
50
51#[cfg(test)]
52mod ignore_test {
53    use super::Ignore;
54    use crate::prelude::filter;
55    use serde_json::json;
56
57    #[test]
58    fn test_ignore() {
59        let json = json!(
60            {
61                "explanation": "test",
62                "media_type": "test",
63                "hdurl": "test",
64                "service_version": "test",
65                "code": 200,
66                "msg": "test"
67            }
68        );
69        let values = filter::<Ignore>(json, &Ignore::new(vec!["explanation", "media_type"]));
70        if let Ok(trimmed) = values {
71            println!("TRIMMED: {:#?}", trimmed);
72            assert!(trimmed.get("explanation").is_none());
73            assert!(trimmed.get("media_type").is_none());
74            assert!(trimmed.get("hdurl").is_some());
75        } else {
76            panic!();
77        }
78
79        let json = json!({
80            "2020-01-01": {
81                "explanation": "test_1",
82                "media_type": "test",
83                "hdurl": "test",
84                "service_version": "test",
85                "code": 200,
86                "msg": "test"
87            },
88            "Object": {
89                "2023-01-11": {
90                    "Object": {
91                        "explanation": "test_3",
92                        "media_type": "test",
93                        "hdurl": "test",
94                        "service_version": "test",
95                        "code": 200,
96                        "msg": "test"
97                    },
98                    "explanation": "test_2",
99                }
100            },
101            "explanation": "test_0"
102        });
103
104        let ignore = Ignore::new(vec!["explanation"]);
105        let trimmed = filter::<Ignore>(json, &ignore).unwrap();
106        println!("TRIMMED: {:#?}", trimmed);
107        assert!(trimmed["2020-01-01"].get("explanation").is_none(), "test_1");
108        assert!(
109            trimmed["Object"]["2023-01-11"]["Object"]
110                .get("explanation")
111                .is_none(),
112            "test_3"
113        );
114        assert!(
115            trimmed["Object"]["2023-01-11"].get("explanation").is_none(),
116            "test_2"
117        );
118        assert!(trimmed.get("explanation").is_none(), "test_0");
119    }
120}