@@ -1053,12 +1053,20 @@ impl RawJsonb<'_> {
10531053 /// along with their corresponding key paths. The key path represents the navigation
10541054 /// path from the root to reach each scalar value.
10551055 ///
1056+ /// # Arguments
1057+ ///
1058+ /// * `ignore_array` - When true, arrays are treated as leaf values and returned as
1059+ /// `Value::Array` without descending into their elements.
1060+ ///
10561061 /// # Returns
10571062 ///
10581063 /// * `Result<Vec<(KeyPaths<'_>, Value<'_>)>>` - A vector of tuples, each containing:
10591064 /// - `KeyPaths`: The path to reach the scalar value
10601065 /// - `Value`: The scalar value itself
10611066 ///
1067+ /// Empty objects or arrays are treated as leaf values and returned as `Value::Object` or
1068+ /// `Value::Array`.
1069+ ///
10621070 /// # Examples
10631071 ///
10641072 /// ```rust
@@ -1067,7 +1075,7 @@ impl RawJsonb<'_> {
10671075 /// let json = r#"{"user": {"name": "Alice", "scores": [85, 92, 78]}}"#;
10681076 /// let jsonb = json.parse::<OwnedJsonb>().unwrap();
10691077 /// let raw_jsonb = jsonb.as_raw();
1070- /// let result = raw_jsonb.extract_scalar_key_values();
1078+ /// let result = raw_jsonb.extract_scalar_key_values(false );
10711079 /// assert!(result.is_ok());
10721080 /// let result = result.unwrap();
10731081 /// assert_eq!(result.len(), 4);
@@ -1077,18 +1085,43 @@ impl RawJsonb<'_> {
10771085 /// // - path: "user", "scores", 1 -> value: 92
10781086 /// // - path: "user", "scores", 2 -> value: 78
10791087 /// ```
1080- pub fn extract_scalar_key_values ( & self ) -> Result < Vec < ( KeyPaths < ' _ > , Value < ' _ > ) > > {
1088+ ///
1089+ /// ```rust
1090+ /// use jsonb::{OwnedJsonb, Value};
1091+ ///
1092+ /// let json = r#"{"user": {"name": "Alice", "scores": [85, 92, 78]}}"#;
1093+ /// let jsonb = json.parse::<OwnedJsonb>().unwrap();
1094+ /// let raw_jsonb = jsonb.as_raw();
1095+ /// let result = raw_jsonb.extract_scalar_key_values(true).unwrap();
1096+ ///
1097+ /// assert_eq!(result.len(), 2);
1098+ /// assert!(result.iter().any(|(_, value)| matches!(value, Value::Array(_))));
1099+ /// // Result contains:
1100+ /// // - path: "user", "name" -> value: "Alice"
1101+ /// // - path: "user", "scores" -> value: [85, 92, 78]
1102+ /// ```
1103+ pub fn extract_scalar_key_values (
1104+ & self ,
1105+ ignore_array : bool ,
1106+ ) -> Result < Vec < ( KeyPaths < ' _ > , Value < ' _ > ) > > {
10811107 let item = JsonbItem :: from_raw_jsonb ( * self ) ?;
10821108 let mut result = Vec :: with_capacity ( 16 ) ;
10831109 let mut current_paths = Vec :: with_capacity ( 3 ) ;
1084- Self :: extract_scalar_key_values_recursive ( item, & mut current_paths, & mut result) ?;
1110+ Self :: extract_scalar_key_values_recursive (
1111+ item,
1112+ ignore_array,
1113+ & mut current_paths,
1114+ & mut result,
1115+ ) ?;
10851116 Ok ( result)
10861117 }
10871118
10881119 /// Helper function for `extract_scalar_key_values` that recursively traverses the JSONB structure.
10891120 ///
10901121 /// This function implements a depth-first traversal of the JSONB document, building up the
10911122 /// key path as it goes and collecting scalar values when it reaches leaf nodes.
1123+ /// Empty objects or arrays are treated as leaf values and returned as `Value::Object` or
1124+ /// `Value::Array` instead of being skipped.
10921125 ///
10931126 /// # Arguments
10941127 ///
@@ -1101,32 +1134,56 @@ impl RawJsonb<'_> {
11011134 /// * `Result<()>` - Success or error during traversal
11021135 fn extract_scalar_key_values_recursive < ' a > (
11031136 current_item : JsonbItem < ' a > ,
1137+ ignore_array : bool ,
11041138 current_paths : & mut Vec < KeyPath < ' a > > ,
11051139 result : & mut Vec < ( KeyPaths < ' a > , Value < ' a > ) > ,
11061140 ) -> Result < ( ) > {
11071141 match current_item {
11081142 JsonbItem :: Raw ( raw) => {
11091143 let object_iter_opt = ObjectIterator :: new ( raw) ?;
11101144 if let Some ( mut object_iter) = object_iter_opt {
1111- for object_result in & mut object_iter {
1112- let ( key, val_item) = object_result?;
1113- current_paths. push ( KeyPath :: Name ( Cow :: Borrowed ( key) ) ) ;
1114- // Recursively handle object values
1115- Self :: extract_scalar_key_values_recursive ( val_item, current_paths, result) ?;
1116- current_paths. pop ( ) ;
1145+ if object_iter. len ( ) > 0 {
1146+ for object_result in & mut object_iter {
1147+ let ( key, val_item) = object_result?;
1148+ current_paths. push ( KeyPath :: Name ( Cow :: Borrowed ( key) ) ) ;
1149+ // Recursively handle object values
1150+ Self :: extract_scalar_key_values_recursive (
1151+ val_item,
1152+ ignore_array,
1153+ current_paths,
1154+ result,
1155+ ) ?;
1156+ current_paths. pop ( ) ;
1157+ }
1158+ return Ok ( ( ) ) ;
11171159 }
1118- return Ok ( ( ) ) ;
1119- }
1120- let array_iter_opt = ArrayIterator :: new ( raw) ?;
1121- if let Some ( array_iter) = array_iter_opt {
1122- for ( index, array_result) in & mut array_iter. enumerate ( ) {
1123- let val_item = array_result?;
1124- current_paths. push ( KeyPath :: Index ( index as i32 ) ) ;
1125- // Recursively handle array values
1126- Self :: extract_scalar_key_values_recursive ( val_item, current_paths, result) ?;
1127- current_paths. pop ( ) ;
1160+ } else if !ignore_array {
1161+ let array_iter_opt = ArrayIterator :: new ( raw) ?;
1162+ if let Some ( array_iter) = array_iter_opt {
1163+ if array_iter. len ( ) > 0 {
1164+ for ( index, array_result) in & mut array_iter. enumerate ( ) {
1165+ let val_item = array_result?;
1166+ current_paths. push ( KeyPath :: Index ( index as i32 ) ) ;
1167+ // Recursively handle array values
1168+ Self :: extract_scalar_key_values_recursive (
1169+ val_item,
1170+ ignore_array,
1171+ current_paths,
1172+ result,
1173+ ) ?;
1174+ current_paths. pop ( ) ;
1175+ }
1176+ return Ok ( ( ) ) ;
1177+ }
11281178 }
11291179 }
1180+ if !current_paths. is_empty ( ) {
1181+ let key_paths = KeyPaths {
1182+ paths : current_paths. clone ( ) ,
1183+ } ;
1184+ let value = raw. to_value ( ) ?;
1185+ result. push ( ( key_paths, value) ) ;
1186+ }
11301187 }
11311188 JsonbItem :: Owned ( _) => unreachable ! ( ) ,
11321189 _ => {
0 commit comments