flatr/
lib.rs

1use colored::Colorize;
2use serde_json::Value;
3use strip_ansi_escapes::strip_str;
4
5/// Returns a String vector of the flattened JSON
6///
7/// # Example
8/// ```
9/// let input = serde_json::json!({
10///     "object": {
11///       "nested_string": "Nested string",
12///       "nested_number": 123,
13///       "nested_boolean": false,
14///       "nested_null_value": null,
15///       "nested_array": ["a", "b", "c"]
16///     }
17/// });
18/// let output = vec![
19///     ".object.nested_string = \"Nested string\"",
20///     ".object.nested_number = 123",
21///     ".object.nested_boolean = false",
22///     ".object.nested_null_value = null",
23///     ".object.nested_array[0] = \"a\"",
24///     ".object.nested_array[1] = \"b\"",
25///     ".object.nested_array[2] = \"c\"",
26/// ];
27/// assert_eq!(flatr::flatten_json(&input), output);
28/// ```
29///
30pub fn flatten_json(input_json: &Value) -> Vec<String> {
31    let mut flattened_strings: Vec<String> = vec![];
32
33    flattenizer(input_json, String::new(), &mut flattened_strings);
34
35    flattened_strings
36}
37
38fn flattenizer(input_json: &Value, prefix: String, flattened_strings: &mut Vec<String>) {
39    match input_json {
40        Value::Object(obj) => {
41            for key in obj.keys() {
42                let new_prefix = format!("{}{}{}", prefix, ".".cyan(), key);
43                flattenizer(&obj[key], new_prefix, flattened_strings);
44            }
45        }
46        Value::Array(array) => {
47            for (index, value) in array.iter().enumerate() {
48                let new_prefix = format!("{}[{}]", prefix, index.to_string().blue());
49                flattenizer(value, new_prefix, flattened_strings);
50            }
51        }
52        _ => {
53            let formatted_value = match input_json {
54                Value::String(v) => format!("\"{v}\"").green(),
55                Value::Number(v) => v.to_string().blue(),
56                Value::Bool(v) => v.to_string().yellow(),
57                Value::Null => "null".to_string().purple().italic(),
58                _ => "".to_string().hidden(),
59            };
60            let entry = format!("{} = {}", prefix, formatted_value);
61            println!("{entry}");
62            flattened_strings.push(strip_str(entry));
63        }
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use crate::flatten_json;
70
71    #[test]
72    fn test_flatten_json() {
73        use serde_json::json;
74
75        let input_json = json!({
76            "string": "Hello, world!",
77            "number": 42,
78            "boolean": true,
79            "null_value": null,
80            "array": [1, 2, 3],
81            "object": {
82                "nested_string": "Nested string",
83                "nested_number": 123,
84                "nested_boolean": false,
85                "nested_null_value": null,
86                "nested_array": ["a", "b", "c"],
87                "nested_object": {
88                    "more_nested_string": "More nested string",
89                    "more_nested_number": 456,
90                    "more_nested_boolean": true,
91                    "more_nested_null_value": null,
92                    "more_nested_array": ["x", "y", "z"]
93                }
94            }
95        });
96
97        let expected_result = vec![
98            ".string = \"Hello, world!\"",
99            ".number = 42",
100            ".boolean = true",
101            ".null_value = null",
102            ".array[0] = 1",
103            ".array[1] = 2",
104            ".array[2] = 3",
105            ".object.nested_string = \"Nested string\"",
106            ".object.nested_number = 123",
107            ".object.nested_boolean = false",
108            ".object.nested_null_value = null",
109            ".object.nested_array[0] = \"a\"",
110            ".object.nested_array[1] = \"b\"",
111            ".object.nested_array[2] = \"c\"",
112            ".object.nested_object.more_nested_string = \"More nested string\"",
113            ".object.nested_object.more_nested_number = 456",
114            ".object.nested_object.more_nested_boolean = true",
115            ".object.nested_object.more_nested_null_value = null",
116            ".object.nested_object.more_nested_array[0] = \"x\"",
117            ".object.nested_object.more_nested_array[1] = \"y\"",
118            ".object.nested_object.more_nested_array[2] = \"z\"",
119        ];
120
121        let actual_result = flatten_json(&input_json);
122
123        assert_eq!(actual_result, expected_result);
124    }
125}