Skip to content

Commit 30b2a13

Browse files
authored
Merge pull request #4 from latonis/keep-array
feat: implement complete array flattening as option
2 parents 3cae6fa + 775ae89 commit 30b2a13

2 files changed

Lines changed: 160 additions & 18 deletions

File tree

readme.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,5 +114,33 @@ fn main() {
114114
}
115115
*/
116116
}
117+
```
118+
119+
### Completely Flat JSON (keep array position in key)
120+
```rust
121+
use serde_json::json;
122+
use smooth_json;
123+
124+
fn main() {
125+
let flattener = smooth_json::Flattener{
126+
alt_array_flattening: true,
127+
..Default::default()
128+
};
117129

130+
let example: Value = json!({
131+
"a": [
132+
"b",
133+
["c", "d"],
134+
]
135+
});
136+
137+
let flattened_example = flattener.flatten(&example);
138+
println!("{}", flattened_example);
139+
/*
140+
{
141+
"a.0": "b",
142+
"a.1.0": "c",
143+
"a.1.1": "d"
144+
}
145+
*/
118146
```

src/lib.rs

Lines changed: 132 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,21 @@ pub struct Flattener<'a> {
3636
/// let flattener = smooth_json::Flattener { alt_array_flattening: true, ..Default::default()};
3737
/// ```
3838
pub alt_array_flattening: bool,
39+
/// Completely flatten JSON and keep array structure in the key when flattening
40+
/// # Examples
41+
/// ```
42+
/// use smooth_json;
43+
/// let flattener = smooth_json::Flattener { preserve_arrays: true, ..Default::default()};
44+
/// ```
45+
pub preserve_arrays: bool,
3946
}
4047

4148
impl<'a> Default for Flattener<'a> {
4249
fn default() -> Self {
4350
Flattener {
4451
separator: ".",
4552
alt_array_flattening: false,
53+
preserve_arrays: false,
4654
}
4755
}
4856
}
@@ -106,17 +114,19 @@ impl<'a> Flattener<'a> {
106114
pub fn flatten(&self, json: &Value) -> Value {
107115
let mut flattened_val = Map::<String, Value>::new();
108116
match json {
109-
Value::Array(obj_arr) => self.flatten_array(&mut flattened_val, "", obj_arr),
117+
Value::Array(obj_arr) => {
118+
self.flatten_array(&mut flattened_val, &"".to_string(), obj_arr)
119+
}
110120
Value::Object(obj_val) => self.flatten_object(&mut flattened_val, None, obj_val, false),
111-
_ => self.flatten_value(&mut flattened_val, "", json, false),
121+
_ => self.flatten_value(&mut flattened_val, &"".to_string(), json, false),
112122
}
113123
Value::Object(flattened_val)
114124
}
115125

116126
fn flatten_object(
117127
&self,
118128
builder: &mut Map<String, Value>,
119-
identifier: Option<&str>,
129+
identifier: Option<&String>,
120130
obj: &Map<String, Value>,
121131
arr: bool,
122132
) {
@@ -128,35 +138,60 @@ impl<'a> Flattener<'a> {
128138

129139
match v {
130140
Value::Object(obj_val) => {
131-
self.flatten_object(builder, Some(expanded_identifier.as_str()), obj_val, arr)
141+
self.flatten_object(builder, Some(&expanded_identifier), obj_val, arr)
132142
}
133-
Value::Array(obj_arr) => {
134-
self.flatten_array(builder, expanded_identifier.as_str(), obj_arr)
135-
}
136-
_ => self.flatten_value(builder, expanded_identifier.as_str(), v, arr),
143+
Value::Array(obj_arr) => self.flatten_array(builder, &expanded_identifier, obj_arr),
144+
_ => self.flatten_value(builder, &expanded_identifier, v, arr),
137145
}
138146
}
139147
}
140148

141-
fn flatten_array(&self, builder: &mut Map<String, Value>, identifier: &str, obj: &Vec<Value>) {
142-
for v in obj {
149+
fn flatten_array(
150+
&self,
151+
builder: &mut Map<String, Value>,
152+
identifier: &String,
153+
obj: &Vec<Value>,
154+
) {
155+
for (k, v) in obj.iter().enumerate() {
156+
let with_key = format!("{identifier}{}{k}", self.separator);
143157
match v {
144158
Value::Object(obj_val) => self.flatten_object(
145159
builder,
146-
Some(identifier),
160+
Some(if self.preserve_arrays {
161+
&with_key
162+
} else {
163+
identifier
164+
}),
147165
obj_val,
148166
self.alt_array_flattening,
149167
),
150-
Value::Array(obj_arr) => self.flatten_array(builder, identifier, obj_arr),
151-
_ => self.flatten_value(builder, identifier, v, true),
168+
Value::Array(obj_arr) => self.flatten_array(
169+
builder,
170+
if self.preserve_arrays {
171+
&with_key
172+
} else {
173+
identifier
174+
},
175+
obj_arr,
176+
),
177+
_ => self.flatten_value(
178+
builder,
179+
if self.preserve_arrays {
180+
&with_key
181+
} else {
182+
identifier
183+
},
184+
v,
185+
self.alt_array_flattening,
186+
),
152187
}
153188
}
154189
}
155190

156191
fn flatten_value(
157192
&self,
158193
builder: &mut Map<String, Value>,
159-
identifier: &str,
194+
identifier: &String,
160195
obj: &Value,
161196
arr: bool,
162197
) {
@@ -264,7 +299,7 @@ mod tests {
264299
json!({
265300
"a.b": ["c", "d", "f"],
266301
"a.c": "e",
267-
"a": [35],
302+
"a": 35,
268303
})
269304
);
270305

@@ -429,19 +464,58 @@ mod tests {
429464
);
430465
}
431466

467+
#[test]
468+
fn array_preserve() {
469+
let flattener = Flattener {
470+
preserve_arrays: true,
471+
..Default::default()
472+
};
473+
474+
let input: Value = json!({
475+
"a": [
476+
{"b": "1"},
477+
{"b": "2"},
478+
{"b": "3"},
479+
]
480+
});
481+
482+
let result: Value = flattener.flatten(&input);
483+
assert_eq!(
484+
result,
485+
json!({
486+
"a.0.b": "1",
487+
"a.1.b": "2",
488+
"a.2.b": "3"
489+
})
490+
);
491+
}
492+
432493
#[test]
433494
fn array_no_collision() {
434495
let flattener = Flattener::new();
496+
let flattener_alt = Flattener {
497+
alt_array_flattening: true,
498+
..Default::default()
499+
};
435500

436501
let input: Value = json!({
437502
"a": [
438503
{"b": ["1"]}
439504
]
440505
});
441506

442-
let result: Value = flattener.flatten(&input);
507+
let flat: Value = flattener.flatten(&input);
508+
let flat_alt = flattener_alt.flatten(&input);
509+
443510
assert_eq!(
444-
result,
511+
flat,
512+
json!({
513+
"a.b": "1"
514+
})
515+
);
516+
517+
assert_eq!(
518+
flat_alt,
445519
json!({
446520
"a.b": ["1"]
447521
})
@@ -474,7 +548,7 @@ mod tests {
474548
});
475549
let result: Value = flattener.flatten(&input);
476550

477-
assert_eq!(result, json!({"": ["a", "b"], ".b": ["1"]}));
551+
assert_eq!(result, json!({"": ["a", "b"], ".b": "1"}));
478552
}
479553

480554
#[test]
@@ -486,4 +560,44 @@ mod tests {
486560

487561
assert_eq!(result, json!({"": "abc"}));
488562
}
563+
564+
#[test]
565+
fn nested_array_preserve() {
566+
let flattener = Flattener {
567+
preserve_arrays: true,
568+
..Default::default()
569+
};
570+
571+
let input: Value = json!({
572+
"a": [
573+
"b",
574+
["c", "d"],
575+
{ "e": ["f", "g"] },
576+
[
577+
{ "h": "i" },
578+
{ "e": ["j", { "z": "y" }] }
579+
],
580+
["l"],
581+
"m"
582+
]
583+
});
584+
585+
let result: Value = flattener.flatten(&input);
586+
587+
assert_eq!(
588+
result,
589+
json!({
590+
"a.0": "b",
591+
"a.1.0": "c",
592+
"a.1.1": "d",
593+
"a.2.e.0": "f",
594+
"a.2.e.1": "g",
595+
"a.3.0.h": "i",
596+
"a.3.1.e.0": "j",
597+
"a.3.1.e.1.z": "y",
598+
"a.4.0": "l",
599+
"a.5": "m"
600+
})
601+
)
602+
}
489603
}

0 commit comments

Comments
 (0)