1#[macro_use]
2extern crate serde_json;
3#[macro_use]
4extern crate error_chain;
5#[macro_use]
6extern crate log;
7
8use serde_json::value::Value;
9use serde_json::map::Map;
10
11error_chain! {
12foreign_links {
13 Json(::serde_json::Error);
14 }
15}
16
17pub fn flatten(nested_value: &Value, flat_value: &mut Value, parent_key: Option<String>, infer_type: bool, separator: Option<&str>) -> Result<()> {
18 if let Some(nested_dict) = nested_value.as_object() {
20 flatten_object(flat_value, &parent_key, nested_dict, infer_type, separator)?;
21 } else if let Some(v_array) = nested_value.as_array() {
22 let new_k = parent_key.unwrap_or_else(||String::from(""));
23 flatten_array(flat_value, &new_k, v_array, infer_type, separator)?;
24 } else {
25 error!("Expected object, found something else: {:?}", nested_value)
26 }
27 Ok(())
28}
29
30
31fn flatten_object(flat_value: &mut Value, parent_key: &Option<String>, nested_dict: &Map<String, Value>, infer_type: bool, separator: Option<&str>) -> Result<()> {
32 let sep = if let Some(sep) = separator {
33 sep
34 } else {
35 "."
36 };
37
38 for (k, v) in nested_dict.iter() {
39 let new_k = match parent_key {
40 Some(ref key) => format!("{}{}{}", key, sep, k),
41 None => k.clone()
42 };
43 if let Some(obj) = v.as_object() {
45 flatten_object(flat_value, &Some(new_k), obj, infer_type, separator)?;
46 } else if let Some(v_array) = v.as_array() {
48 if !v_array.is_empty() {
50 flatten_array(flat_value, &new_k, v_array, infer_type, separator)?;
52 } else if let Some(value) = flat_value.as_object_mut() {
54 let empty: Vec<Value> = vec!();
55 value.insert(k.to_string(), json!(empty));
56 }
57 } else if let Some(value) = flat_value.as_object_mut() {
59 infer_type_and_insert(v, new_k, value, infer_type)?;
60 }
61 }
62 Ok(())
63}
64
65fn infer_type_and_insert(v: &Value, new_k: String, value: &mut Map<String, Value>, infer_type: bool) -> Result<()> {
66 let new_val;
67 if infer_type {
68 if let Some(string) = v.as_str() {
69 new_val = match string.parse::<i64>() {
70 Ok(i) => serde_json::to_value(i)?,
71 Err(_) => match string.parse::<f64>() {
72 Ok(f) => serde_json::to_value(f)?,
73 Err(_) => match string.parse::<bool>() {
74 Ok(b) => serde_json::to_value(b)?,
75 Err(_) => serde_json::to_value(string)?
76 }
77 }
78 };
79 } else {
80 new_val = v.clone();
81 }
82 } else {
83 new_val = v.clone();
84 };
85 value.insert(new_k, new_val);
86 Ok(())
87}
88
89fn flatten_array(flat_value: &mut Value, new_k: &str, v_array: &[Value], infer_type: bool, separator: Option<&str>) -> Result<()> {
90 for (i, obj) in v_array.iter().enumerate() {
91 let array_key = format!("{}.{}", new_k, i);
92 if obj.is_object() | obj.is_array() {
94 flatten(obj, flat_value, Some(array_key), infer_type, separator)?;
95 } else if let Some(value) = flat_value.as_object_mut() {
97 infer_type_and_insert(obj, array_key, value, infer_type)?;
98 }
99 }
100 Ok(())
101}
102
103#[cfg(test)]
104mod tests {
105 use super::flatten;
106
107 #[test]
108 fn single_key_value() {
109 let obj = json!({"key": "value"});
110
111 let mut flat = json!({});
112 flatten(&obj, &mut flat, None, true, None).unwrap();
113 assert_eq!(obj, json!(flat));
114 }
115
116 #[test]
117 fn single_int_value() {
118 let obj = json!({"key": 1});
119
120 let mut flat = json!({});
121 flatten(&obj, &mut flat, None, true, None).unwrap();
122 assert_eq!(json!({"key": 1}), json!(flat));
123 }
124
125 #[test]
126 fn single_int_as_str_value() {
127 let obj = json!({"key": "1"});
128
129 let mut flat = json!({});
130 flatten(&obj, &mut flat, None, true, None).unwrap();
131 assert_eq!(json!({"key": 1}), json!(flat));
132 }
133
134 #[test]
135 fn single_int_as_str_no_infer_type_value() {
136 let obj = json!({"key": "1"});
137
138 let mut flat = json!({});
139 flatten(&obj, &mut flat, None, false, None).unwrap();
140 assert_eq!(json!({"key": "1"}), json!(flat));
141 }
142
143 #[test]
144 fn single_float_as_str_value() {
145 let obj = json!({"key": "1.0"});
146
147 let mut flat = json!({});
148 flatten(&obj, &mut flat, None, true, None).unwrap();
149 assert_eq!(json!({"key": 1.}), json!(flat));
150 }
151
152 #[test]
153 fn single_bool_as_str_value() {
154 let obj = json!({"key": "true"});
155
156 let mut flat = json!({});
157 flatten(&obj, &mut flat, None, true, None).unwrap();
158 assert_eq!(json!({"key": true}), json!(flat));
159 }
160
161 #[test]
162 fn multi_key_value() {
163 let obj = json!({"key1": "value1", "key2": "value2"});
164
165 let mut flat = json!({});
166 flatten(&obj, &mut flat, None, true, None).unwrap();
167 assert_eq!(obj, json!(flat));
168 }
169
170 #[test]
171 fn nested_single_key_value() {
172 let obj = json!({"key": "value", "nested_key": {"key":"value"}});
173
174 let mut flat = json!({});
175 flatten(&obj, &mut flat, None, true, None).unwrap();
176 assert_eq!(json!({"key": "value", "nested_key.key": "value"}), json!(flat));
177 }
178
179
180 #[test]
181 fn nested_multiple_key_value() {
182 let obj = json!({"key": "value", "nested_key": {"key1":"value1", "key2": "value2"}});
183
184 let mut flat = json!({});
185 flatten(&obj, &mut flat, None, true, None).unwrap();
186 assert_eq!(json!({"key": "value", "nested_key.key1": "value1", "nested_key.key2": "value2"}), json!(flat));
187 }
188
189 #[test]
190 fn top_level_array() {
191 let obj = json!(["value1", "value2"]);
192
193 let mut flat = json!({});
194 flatten(&obj, &mut flat, None, true, None).unwrap();
195 assert_eq!(json!({".0": "value1", ".1": "value2"}), json!(flat));
196 }
197
198 #[test]
199 fn nested_array() {
200 let obj = json!({"key": ["value1", "value2"]});
201
202 let mut flat = json!({});
203 flatten(&obj, &mut flat, None, true, None).unwrap();
204 assert_eq!(json!({"key.0": "value1", "key.1": "value2"}), json!(flat));
205 }
206
207 #[test]
208 fn nested_obj_array() {
209 let obj = json!({"key": ["value1", {"key": "value2"}]});
210
211 let mut flat = json!({});
212 flatten(&obj, &mut flat, None, true, None).unwrap();
213 assert_eq!(json!({"key.0": "value1", "key.1.key": "value2"}), json!(flat));
214 }
215
216 #[test]
217 fn complex_nested_struct() {
218 let obj = json!({"simple_key": "simple_value", "key": ["value1", {"key": "value2"}, {"nested_array": ["nested1", "nested2", ["nested3", "nested4"]]}]});
219
220 let mut flat = json!({});
221 flatten(&obj, &mut flat, None, true, None).unwrap();
222 assert_eq!(json!({"simple_key": "simple_value", "key.0": "value1", "key.1.key": "value2", "key.2.nested_array.0": "nested1", "key.2.nested_array.1": "nested2", "key.2.nested_array.2.0": "nested3", "key.2.nested_array.2.1": "nested4"}), json!(flat));
223 }
224}