@@ -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
4148impl < ' 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