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