base_d/encoders/algorithms/schema/serializers/
json.rs1use crate::encoders::algorithms::schema::serializers::OutputSerializer;
2use crate::encoders::algorithms::schema::types::*;
3use serde_json::{Map, Value, json};
4use std::collections::HashMap;
5
6pub struct JsonSerializer;
7
8impl OutputSerializer for JsonSerializer {
9 type Error = SchemaError;
10
11 fn serialize(ir: &IntermediateRepresentation, pretty: bool) -> Result<String, Self::Error> {
12 if ir.header.row_count == 0 {
13 return Err(SchemaError::InvalidInput(
14 "No rows to serialize".to_string(),
15 ));
16 }
17
18 let mut rows = Vec::new();
20 for row_idx in 0..ir.header.row_count {
21 let mut row_map = HashMap::new();
22
23 for (field_idx, field) in ir.header.fields.iter().enumerate() {
24 let value = ir
25 .get_value(row_idx, field_idx)
26 .ok_or_else(|| SchemaError::InvalidInput("Missing value".to_string()))?;
27
28 let json_value = if ir.is_null(row_idx, field_idx) {
29 Value::Null
30 } else {
31 schema_value_to_json(value)?
32 };
33
34 row_map.insert(field.name.clone(), json_value);
35 }
36
37 rows.push(row_map);
38 }
39
40 let mut unflattened_rows = Vec::new();
42 for row_map in rows {
43 let unflattened = unflatten_object(row_map);
44 unflattened_rows.push(unflattened);
45 }
46
47 let result = if ir.header.row_count == 1 {
49 unflattened_rows.into_iter().next().unwrap()
51 } else {
52 Value::Array(unflattened_rows)
54 };
55
56 let final_result = if let Some(root_key) = &ir.header.root_key {
58 let mut obj = Map::new();
59 obj.insert(root_key.clone(), result);
60 Value::Object(obj)
61 } else {
62 result
63 };
64
65 if pretty {
67 serde_json::to_string_pretty(&final_result)
68 .map_err(|e| SchemaError::InvalidInput(format!("JSON serialization failed: {}", e)))
69 } else {
70 serde_json::to_string(&final_result)
71 .map_err(|e| SchemaError::InvalidInput(format!("JSON serialization failed: {}", e)))
72 }
73 }
74}
75
76fn schema_value_to_json(value: &SchemaValue) -> Result<Value, SchemaError> {
78 match value {
79 SchemaValue::U64(n) => Ok(json!(*n)),
80 SchemaValue::I64(n) => Ok(json!(*n)),
81 SchemaValue::F64(n) => Ok(json!(*n)),
82 SchemaValue::String(s) => Ok(json!(s)),
83 SchemaValue::Bool(b) => Ok(json!(*b)),
84 SchemaValue::Null => Ok(Value::Null),
85 SchemaValue::Array(arr) => {
86 let mut json_arr = Vec::new();
87 for item in arr {
88 json_arr.push(schema_value_to_json(item)?);
89 }
90 Ok(Value::Array(json_arr))
91 }
92 }
93}
94
95fn unflatten_object(flat: HashMap<String, Value>) -> Value {
97 let mut result = Map::new();
98
99 for (key, value) in flat {
100 let parts: Vec<&str> = key.split('.').collect();
101 insert_nested(&mut result, &parts, value);
102 }
103
104 Value::Object(result)
105}
106
107fn insert_nested(obj: &mut Map<String, Value>, parts: &[&str], value: Value) {
109 if parts.is_empty() {
110 return;
111 }
112
113 if parts.len() == 1 {
114 obj.insert(parts[0].to_string(), value);
115 return;
116 }
117
118 let key = parts[0];
119 let remaining = &parts[1..];
120
121 let nested = obj
122 .entry(key.to_string())
123 .or_insert_with(|| Value::Object(Map::new()));
124
125 if let Value::Object(nested_obj) = nested {
126 insert_nested(nested_obj, remaining, value);
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133
134 #[test]
135 fn test_simple_object() {
136 let fields = vec![
137 FieldDef::new("id", FieldType::U64),
138 FieldDef::new("name", FieldType::String),
139 ];
140 let header = SchemaHeader::new(1, fields);
141 let values = vec![
142 SchemaValue::U64(1),
143 SchemaValue::String("alice".to_string()),
144 ];
145 let ir = IntermediateRepresentation::new(header, values).unwrap();
146
147 let output = JsonSerializer::serialize(&ir, false).unwrap();
148 let parsed: Value = serde_json::from_str(&output).unwrap();
149
150 assert_eq!(parsed["id"], json!(1));
151 assert_eq!(parsed["name"], json!("alice"));
152 }
153
154 #[test]
155 fn test_array_of_objects() {
156 let fields = vec![FieldDef::new("id", FieldType::U64)];
157 let header = SchemaHeader::new(2, fields);
158 let values = vec![SchemaValue::U64(1), SchemaValue::U64(2)];
159 let ir = IntermediateRepresentation::new(header, values).unwrap();
160
161 let output = JsonSerializer::serialize(&ir, false).unwrap();
162 let parsed: Value = serde_json::from_str(&output).unwrap();
163
164 assert!(parsed.is_array());
165 assert_eq!(parsed[0]["id"], json!(1));
166 assert_eq!(parsed[1]["id"], json!(2));
167 }
168
169 #[test]
170 fn test_nested_object() {
171 let fields = vec![FieldDef::new("user.profile.name", FieldType::String)];
172 let header = SchemaHeader::new(1, fields);
173 let values = vec![SchemaValue::String("alice".to_string())];
174 let ir = IntermediateRepresentation::new(header, values).unwrap();
175
176 let output = JsonSerializer::serialize(&ir, false).unwrap();
177 let parsed: Value = serde_json::from_str(&output).unwrap();
178
179 assert_eq!(parsed["user"]["profile"]["name"], json!("alice"));
180 }
181
182 #[test]
183 fn test_root_key() {
184 let mut header = SchemaHeader::new(1, vec![FieldDef::new("id", FieldType::U64)]);
185 header.root_key = Some("users".to_string());
186 header.set_flag(FLAG_HAS_ROOT_KEY);
187
188 let values = vec![SchemaValue::U64(1)];
189 let ir = IntermediateRepresentation::new(header, values).unwrap();
190
191 let output = JsonSerializer::serialize(&ir, false).unwrap();
192 let parsed: Value = serde_json::from_str(&output).unwrap();
193
194 assert!(parsed["users"].is_object());
195 assert_eq!(parsed["users"]["id"], json!(1));
196 }
197
198 #[test]
199 fn test_null_handling() {
200 let mut header = SchemaHeader::new(
201 1,
202 vec![
203 FieldDef::new("name", FieldType::String),
204 FieldDef::new("age", FieldType::U64),
205 ],
206 );
207
208 let mut null_bitmap = vec![0u8; 1];
210 null_bitmap[0] |= 1 << 1; header.null_bitmap = Some(null_bitmap);
212 header.set_flag(FLAG_HAS_NULLS);
213
214 let values = vec![SchemaValue::String("alice".to_string()), SchemaValue::Null];
215 let ir = IntermediateRepresentation::new(header, values).unwrap();
216
217 let output = JsonSerializer::serialize(&ir, false).unwrap();
218 let parsed: Value = serde_json::from_str(&output).unwrap();
219
220 assert_eq!(parsed["name"], json!("alice"));
221 assert_eq!(parsed["age"], Value::Null);
222 }
223
224 #[test]
225 fn test_homogeneous_array() {
226 let fields = vec![FieldDef::new(
227 "scores",
228 FieldType::Array(Box::new(FieldType::U64)),
229 )];
230 let header = SchemaHeader::new(1, fields);
231 let values = vec![SchemaValue::Array(vec![
232 SchemaValue::U64(1),
233 SchemaValue::U64(2),
234 SchemaValue::U64(3),
235 ])];
236 let ir = IntermediateRepresentation::new(header, values).unwrap();
237
238 let output = JsonSerializer::serialize(&ir, false).unwrap();
239 let parsed: Value = serde_json::from_str(&output).unwrap();
240
241 assert_eq!(parsed["scores"], json!([1, 2, 3]));
242 }
243
244 #[test]
245 fn test_empty_array() {
246 let fields = vec![FieldDef::new(
247 "items",
248 FieldType::Array(Box::new(FieldType::Null)),
249 )];
250 let header = SchemaHeader::new(1, fields);
251 let values = vec![SchemaValue::Array(vec![])];
252 let ir = IntermediateRepresentation::new(header, values).unwrap();
253
254 let output = JsonSerializer::serialize(&ir, false).unwrap();
255 let parsed: Value = serde_json::from_str(&output).unwrap();
256
257 assert_eq!(parsed["items"], json!([]));
258 }
259
260 #[test]
261 fn test_deep_nesting() {
262 let fields = vec![FieldDef::new("a.b.c.d", FieldType::U64)];
263 let header = SchemaHeader::new(1, fields);
264 let values = vec![SchemaValue::U64(1)];
265 let ir = IntermediateRepresentation::new(header, values).unwrap();
266
267 let output = JsonSerializer::serialize(&ir, false).unwrap();
268 let parsed: Value = serde_json::from_str(&output).unwrap();
269
270 assert_eq!(parsed["a"]["b"]["c"]["d"], json!(1));
271 }
272
273 #[test]
274 fn test_unflatten_object() {
275 let mut flat = HashMap::new();
276 flat.insert("a.b".to_string(), json!(1));
277
278 let unflattened = unflatten_object(flat);
279
280 assert_eq!(unflattened["a"]["b"], json!(1));
281 }
282
283 #[test]
284 fn test_pretty_output() {
285 let fields = vec![
286 FieldDef::new("id", FieldType::U64),
287 FieldDef::new("name", FieldType::String),
288 ];
289 let header = SchemaHeader::new(1, fields);
290 let values = vec![
291 SchemaValue::U64(1),
292 SchemaValue::String("alice".to_string()),
293 ];
294 let ir = IntermediateRepresentation::new(header, values).unwrap();
295
296 let compact = JsonSerializer::serialize(&ir, false).unwrap();
298 assert!(!compact.contains('\n'));
299 assert_eq!(compact, r#"{"id":1,"name":"alice"}"#);
300
301 let pretty = JsonSerializer::serialize(&ir, true).unwrap();
303 assert!(pretty.contains('\n'));
304 assert!(pretty.contains(" ")); let compact_value: Value = serde_json::from_str(&compact).unwrap();
308 let pretty_value: Value = serde_json::from_str(&pretty).unwrap();
309 assert_eq!(compact_value, pretty_value);
310 }
311}