1pub use self::Flattener as Flatten;
2use serde_json::{Map, Value};
3
4pub struct Flattener {
5 delimiter: char,
6}
7
8impl Default for Flattener {
9 fn default() -> Self {
10 Self { delimiter: '.' }
11 }
12}
13
14impl Flattener {
15 pub fn new(delimiter: char) -> Self {
16 Self { delimiter }
17 }
18 fn flatten_map(&self, map: &Map<String, Value>, prefix: &str, result: &mut Map<String, Value>) {
19 for (k, v) in map.iter() {
20 let new_pref = if prefix.is_empty() {
21 k.clone()
22 } else {
23 format!("{}{}{}", prefix, self.delimiter, k)
24 };
25 match v {
26 serde_json::Value::Object(inner) => {
27 self.flatten_map(inner, &new_pref, result);
28 }
29 serde_json::Value::Array(arr) => {
30 self.flatten_array(arr, &new_pref, result);
31 }
32 _ => {
33 result.insert(new_pref, v.clone());
34 }
35 }
36 }
37 }
38 fn flatten_array(
39 &self,
40 array: &[serde_json::Value],
41 prefix: &str,
42 result: &mut Map<String, Value>,
43 ) {
44 for (index, value) in array.iter().enumerate() {
45 let new_prefix = format!("{}{}{}", prefix, self.delimiter, index);
46 match value {
47 serde_json::Value::Object(inner_map) => {
48 self.flatten_map(inner_map, &new_prefix, result);
49 }
50 serde_json::Value::Array(inner_array) => {
51 self.flatten_array(inner_array, &new_prefix, result);
52 }
53 _ => {
54 result.insert(new_prefix, value.clone());
55 }
56 }
57 }
58 }
59}
60
61impl crate::filter::Filter for Flattener {
62 type Output = Value;
63
64 fn filter(&self, json: Value) -> Result<Self::Output, anyhow::Error> {
65 let mut result = Map::new();
66 match json {
67 Value::Object(map) => {
68 self.flatten_map(&map, "", &mut result);
69 }
70 Value::Array(arr) => {
71 self.flatten_array(&arr, "", &mut result);
72 }
73 _ => {
74 return Err(anyhow::anyhow!(
75 "Flattener can only be used on objects or arrays"
76 ))
77 }
78 }
79 return Ok(Value::Object(result));
80 }
81}
82
83#[cfg(test)]
84mod flatten_test {
85 use super::*;
86 use crate::prelude::{filter, Filter};
87
88 #[test]
89 fn test_flatten() {
90 let json = serde_json::json!({
91 "a": {
92 "b": {
93 "c": {
94 "d": "value"
95 }
96 }
97 },
98 "e": "value"
99 });
100
101 let expected = serde_json::json!({
102 "a.b.c.d": "value",
103 "e": "value"
104 });
105
106 let result = filter::<Flatten>(json, &Flatten::default()).unwrap();
107 println!("{:?}", result);
108 assert_eq!(result, expected);
109 }
110}