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 {
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 obj.insert(root_key.clone(), result);
61 Value::Object(obj)
62 } else {
63 result
64 };
65
66 if pretty {
68 serde_json::to_string_pretty(&final_result)
69 .map_err(|e| SchemaError::InvalidInput(format!("JSON serialization failed: {}", e)))
70 } else {
71 serde_json::to_string(&final_result)
72 .map_err(|e| SchemaError::InvalidInput(format!("JSON serialization failed: {}", e)))
73 }
74 }
75}
76
77fn schema_value_to_json(value: &SchemaValue) -> Result<Value, SchemaError> {
79 match value {
80 SchemaValue::U64(n) => Ok(json!(*n)),
81 SchemaValue::I64(n) => Ok(json!(*n)),
82 SchemaValue::F64(n) => Ok(json!(*n)),
83 SchemaValue::String(s) => Ok(json!(s)),
84 SchemaValue::Bool(b) => Ok(json!(*b)),
85 SchemaValue::Null => Ok(Value::Null),
86 SchemaValue::Array(arr) => {
87 let mut json_arr = Vec::new();
88 for item in arr {
89 json_arr.push(schema_value_to_json(item)?);
90 }
91 Ok(Value::Array(json_arr))
92 }
93 }
94}
95
96fn unflatten_object(flat: HashMap<String, Value>) -> Value {
98 let mut result = Map::new();
99
100 for (key, value) in flat {
101 let parts: Vec<&str> = key.split(NEST_SEP).collect();
102 insert_nested(&mut result, &parts, value);
103 }
104
105 Value::Object(result)
106}
107
108fn insert_nested(obj: &mut Map<String, Value>, parts: &[&str], value: Value) {
110 if parts.is_empty() {
111 return;
112 }
113
114 if parts.len() == 1 {
115 obj.insert(parts[0].to_string(), value);
116 return;
117 }
118
119 let key = parts[0];
120 let remaining = &parts[1..];
121
122 let nested = obj
123 .entry(key.to_string())
124 .or_insert_with(|| Value::Object(Map::new()));
125
126 if let Value::Object(nested_obj) = nested {
127 insert_nested(nested_obj, remaining, value);
128 }
129}
130
131#[cfg(test)]
132mod tests {
133 use super::*;
134
135 #[test]
136 fn test_simple_object() {
137 let fields = vec![
138 FieldDef::new("id", FieldType::U64),
139 FieldDef::new("name", FieldType::String),
140 ];
141 let header = SchemaHeader::new(1, fields);
142 let values = vec![
143 SchemaValue::U64(1),
144 SchemaValue::String("alice".to_string()),
145 ];
146 let ir = IntermediateRepresentation::new(header, values).unwrap();
147
148 let output = JsonSerializer::serialize(&ir, false).unwrap();
149 let parsed: Value = serde_json::from_str(&output).unwrap();
150
151 assert_eq!(parsed["id"], json!(1));
152 assert_eq!(parsed["name"], json!("alice"));
153 }
154
155 #[test]
156 fn test_array_of_objects() {
157 let fields = vec![FieldDef::new("id", FieldType::U64)];
158 let header = SchemaHeader::new(2, fields);
159 let values = vec![SchemaValue::U64(1), SchemaValue::U64(2)];
160 let ir = IntermediateRepresentation::new(header, values).unwrap();
161
162 let output = JsonSerializer::serialize(&ir, false).unwrap();
163 let parsed: Value = serde_json::from_str(&output).unwrap();
164
165 assert!(parsed.is_array());
166 assert_eq!(parsed[0]["id"], json!(1));
167 assert_eq!(parsed[1]["id"], json!(2));
168 }
169
170 #[test]
171 fn test_nested_object() {
172 let fields = vec![FieldDef::new("user჻profile჻name", FieldType::String)];
173 let header = SchemaHeader::new(1, fields);
174 let values = vec![SchemaValue::String("alice".to_string())];
175 let ir = IntermediateRepresentation::new(header, values).unwrap();
176
177 let output = JsonSerializer::serialize(&ir, false).unwrap();
178 let parsed: Value = serde_json::from_str(&output).unwrap();
179
180 assert_eq!(parsed["user"]["profile"]["name"], json!("alice"));
181 }
182
183 #[test]
184 fn test_root_key() {
185 let mut header = SchemaHeader::new(1, vec![FieldDef::new("id", FieldType::U64)]);
186 header.root_key = Some("users".to_string());
187 header.set_flag(FLAG_HAS_ROOT_KEY);
188
189 let values = vec![SchemaValue::U64(1)];
190 let ir = IntermediateRepresentation::new(header, values).unwrap();
191
192 let output = JsonSerializer::serialize(&ir, false).unwrap();
193 let parsed: Value = serde_json::from_str(&output).unwrap();
194
195 assert!(parsed["users"].is_object());
196 assert_eq!(parsed["users"]["id"], json!(1));
197 }
198
199 #[test]
200 fn test_null_handling() {
201 let mut header = SchemaHeader::new(
202 1,
203 vec![
204 FieldDef::new("name", FieldType::String),
205 FieldDef::new("age", FieldType::U64),
206 ],
207 );
208
209 let mut null_bitmap = vec![0u8; 1];
211 null_bitmap[0] |= 1 << 1; header.null_bitmap = Some(null_bitmap);
213 header.set_flag(FLAG_HAS_NULLS);
214
215 let values = vec![SchemaValue::String("alice".to_string()), SchemaValue::Null];
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_eq!(parsed["name"], json!("alice"));
222 assert_eq!(parsed["age"], Value::Null);
223 }
224
225 #[test]
226 fn test_homogeneous_array() {
227 let fields = vec![FieldDef::new(
228 "scores",
229 FieldType::Array(Box::new(FieldType::U64)),
230 )];
231 let header = SchemaHeader::new(1, fields);
232 let values = vec![SchemaValue::Array(vec![
233 SchemaValue::U64(1),
234 SchemaValue::U64(2),
235 SchemaValue::U64(3),
236 ])];
237 let ir = IntermediateRepresentation::new(header, values).unwrap();
238
239 let output = JsonSerializer::serialize(&ir, false).unwrap();
240 let parsed: Value = serde_json::from_str(&output).unwrap();
241
242 assert_eq!(parsed["scores"], json!([1, 2, 3]));
243 }
244
245 #[test]
246 fn test_empty_array() {
247 let fields = vec![FieldDef::new(
248 "items",
249 FieldType::Array(Box::new(FieldType::Null)),
250 )];
251 let header = SchemaHeader::new(1, fields);
252 let values = vec![SchemaValue::Array(vec![])];
253 let ir = IntermediateRepresentation::new(header, values).unwrap();
254
255 let output = JsonSerializer::serialize(&ir, false).unwrap();
256 let parsed: Value = serde_json::from_str(&output).unwrap();
257
258 assert_eq!(parsed["items"], json!([]));
259 }
260
261 #[test]
262 fn test_deep_nesting() {
263 let fields = vec![FieldDef::new("a჻b჻c჻d", FieldType::U64)];
264 let header = SchemaHeader::new(1, fields);
265 let values = vec![SchemaValue::U64(1)];
266 let ir = IntermediateRepresentation::new(header, values).unwrap();
267
268 let output = JsonSerializer::serialize(&ir, false).unwrap();
269 let parsed: Value = serde_json::from_str(&output).unwrap();
270
271 assert_eq!(parsed["a"]["b"]["c"]["d"], json!(1));
272 }
273
274 #[test]
275 fn test_unflatten_object() {
276 let mut flat = HashMap::new();
277 flat.insert("a჻b".to_string(), json!(1));
278
279 let unflattened = unflatten_object(flat);
280
281 assert_eq!(unflattened["a"]["b"], json!(1));
282 }
283
284 #[test]
285 fn test_pretty_output() {
286 let fields = vec![
287 FieldDef::new("id", FieldType::U64),
288 FieldDef::new("name", FieldType::String),
289 ];
290 let header = SchemaHeader::new(1, fields);
291 let values = vec![
292 SchemaValue::U64(1),
293 SchemaValue::String("alice".to_string()),
294 ];
295 let ir = IntermediateRepresentation::new(header, values).unwrap();
296
297 let compact = JsonSerializer::serialize(&ir, false).unwrap();
299 assert!(!compact.contains('\n'));
300 assert_eq!(compact, r#"{"id":1,"name":"alice"}"#);
301
302 let pretty = JsonSerializer::serialize(&ir, true).unwrap();
304 assert!(pretty.contains('\n'));
305 assert!(pretty.contains(" ")); let compact_value: Value = serde_json::from_str(&compact).unwrap();
309 let pretty_value: Value = serde_json::from_str(&pretty).unwrap();
310 assert_eq!(compact_value, pretty_value);
311 }
312}