Skip to content

Commit cbd21a3

Browse files
enhancement: implement generic flattening
helps to flatten the nested json such that all list type fields gets converted to primitive type hence spliting the repeating array to multiple rows eg. `[ { "id": 1, "name": "John Doe", "addresses": [ { "street": "123 Main St", "city": "Springfield", "state": "IL", "zip": "62701" }, { "street": "456 Elm St", "city": "Springfield", "state": "IL", "zip": "62702" } ] } ] ` gets coverted to below ` [ { "id": 1, "name": "John Doe", "addresses_street": "123 Main St", "addresses_city": "Springfield", "addresses_state": "IL", "addresses_zip": "62701", }, { "id": 1, "name": "John Doe", "addresses_street": "456 Elm St", "addresses_city": "Springfield", "addresses_state": "IL", "addresses_zip": "62702", } ] `
1 parent 0353dc4 commit cbd21a3

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed

src/utils/json/flatten.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,61 @@ pub fn flatten_array_objects(
304304
Ok(())
305305
}
306306

307+
pub fn flatten_json(value: &Value) -> Vec<Value> {
308+
match value {
309+
Value::Array(arr) => {
310+
let mut results = Vec::new();
311+
for item in arr {
312+
results.extend(flatten_json(item));
313+
}
314+
results
315+
}
316+
Value::Object(map) => {
317+
let mut results = vec![map.clone()];
318+
for (key, val) in map {
319+
if let Value::Array(arr) = val {
320+
let mut new_results = Vec::new();
321+
for item in arr {
322+
let flattened_items = flatten_json(item);
323+
for flattened_item in flattened_items {
324+
for result in &results {
325+
let mut new_obj = result.clone();
326+
new_obj.insert(key.clone(), flattened_item.clone());
327+
new_results.push(new_obj);
328+
}
329+
}
330+
}
331+
results = new_results;
332+
} else if let Value::Object(_) = val {
333+
let nested_results = flatten_json(val);
334+
let mut new_results = Vec::new();
335+
for nested_result in nested_results {
336+
for result in &results {
337+
let mut new_obj = result.clone();
338+
new_obj.insert(key.clone(), nested_result.clone());
339+
new_results.push(new_obj);
340+
}
341+
}
342+
results = new_results;
343+
}
344+
}
345+
results.into_iter().map(Value::Object).collect()
346+
}
347+
_ => vec![value.clone()],
348+
}
349+
}
350+
351+
pub fn convert_to_array(flatterned: Vec<Value>) -> Value {
352+
let mut result = Vec::new();
353+
for item in flatterned {
354+
let mut map = Map::new();
355+
for (key, value) in item.as_object().unwrap() {
356+
map.insert(key.clone(), value.clone());
357+
}
358+
result.push(Value::Object(map));
359+
}
360+
Value::Array(result)
361+
}
307362
#[cfg(test)]
308363
mod tests {
309364
use crate::utils::json::flatten::flatten_array_objects;

src/utils/json/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ pub fn flatten_json_body(
2828
custom_partition: Option<String>,
2929
validation_required: bool,
3030
) -> Result<Value, anyhow::Error> {
31+
let nested_value = flatten::convert_to_array(flatten::flatten_json(&body));
3132
flatten::flatten(
32-
body,
33+
nested_value,
3334
"_",
3435
time_partition,
3536
time_partition_limit,

0 commit comments

Comments
 (0)