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}