1use super::data_value::DataValue;
7use super::number::NumberValue;
8use crate::arena::DataArena;
9use serde_json::{Map as JsonMap, Number as JsonNumber, Value as JsonValue};
10use std::collections::HashMap;
11
12pub trait FromJson<'a> {
14 fn from_json(json: &JsonValue, arena: &'a DataArena) -> DataValue<'a>;
16}
17
18pub trait ToJson {
20 fn to_json(&self) -> JsonValue;
22}
23
24impl<'a> FromJson<'a> for DataValue<'a> {
25 fn from_json(json: &JsonValue, arena: &'a DataArena) -> DataValue<'a> {
26 match json {
27 JsonValue::Null => DataValue::null(),
28 JsonValue::Bool(b) => DataValue::bool(*b),
29 JsonValue::Number(n) => {
30 if let Some(i) = n.as_i64() {
31 DataValue::integer(i)
32 } else if let Some(f) = n.as_f64() {
33 DataValue::float(f)
34 } else {
35 DataValue::null()
37 }
38 }
39 JsonValue::String(s) => {
40 if let Ok(dt) = super::parse_datetime(s) {
42 return DataValue::datetime(dt);
43 }
44
45 if let Ok(duration) = super::parse_duration(s) {
47 return DataValue::duration(duration);
48 }
49
50 DataValue::string(arena, s)
52 }
53 JsonValue::Array(arr) => {
54 let mut values = Vec::with_capacity(arr.len());
56
57 for item in arr.iter() {
59 values.push(DataValue::from_json(item, arena));
60 }
61
62 DataValue::array(arena, &values)
64 }
65 JsonValue::Object(obj) => {
66 let mut entries = Vec::with_capacity(obj.len());
68
69 for (key, value) in obj.iter() {
71 let interned_key = arena.intern_str(key);
72 entries.push((interned_key, DataValue::from_json(value, arena)));
73 }
74
75 DataValue::object(arena, &entries)
77 }
78 }
79 }
80}
81
82impl ToJson for DataValue<'_> {
83 fn to_json(&self) -> JsonValue {
84 match self {
85 DataValue::Null => JsonValue::Null,
86 DataValue::Bool(b) => JsonValue::Bool(*b),
87 DataValue::Number(n) => {
88 match n {
89 NumberValue::Integer(i) => {
90 JsonValue::Number((*i).into())
92 }
93 NumberValue::Float(f) => {
94 if let Some(num) = JsonNumber::from_f64(*f) {
95 JsonValue::Number(num)
96 } else {
97 JsonValue::Null
99 }
100 }
101 }
102 }
103 DataValue::String(s) => JsonValue::String(s.to_string()),
104 DataValue::Array(arr) => {
105 let json_arr: Vec<JsonValue> = arr.iter().map(|item| item.to_json()).collect();
106 JsonValue::Array(json_arr)
107 }
108 DataValue::Object(entries) => {
109 let mut map = JsonMap::new();
110 for (key, value) in entries.iter() {
111 map.insert((*key).to_string(), value.to_json());
112 }
113 JsonValue::Object(map)
114 }
115 DataValue::DateTime(dt) => {
116 JsonValue::String(dt.to_rfc3339())
118 }
119 DataValue::Duration(d) => {
120 let total_seconds = d.num_seconds();
122 let days = total_seconds / 86400;
123 let hours = (total_seconds % 86400) / 3600;
124 let minutes = (total_seconds % 3600) / 60;
125 let seconds = total_seconds % 60;
126
127 if days > 0 {
128 JsonValue::String(format!("{}d:{}h:{}m:{}s", days, hours, minutes, seconds))
129 } else if hours > 0 {
130 JsonValue::String(format!("{}h:{}m:{}s", hours, minutes, seconds))
131 } else if minutes > 0 {
132 JsonValue::String(format!("{}m:{}s", minutes, seconds))
133 } else {
134 JsonValue::String(format!("{}s", seconds))
135 }
136 }
137 }
138 }
139}
140
141pub fn json_to_data_value<'a>(json: &JsonValue, arena: &'a DataArena) -> DataValue<'a> {
143 DataValue::from_json(json, arena)
144}
145
146pub fn data_value_to_json(value: &DataValue<'_>) -> JsonValue {
148 value.to_json()
149}
150
151pub fn hash_map_to_data_value<'a, V>(
153 map: &HashMap<String, V>,
154 arena: &'a DataArena,
155 value_converter: impl Fn(&V, &'a DataArena) -> DataValue<'a>,
156) -> DataValue<'a> {
157 let entries: Vec<(&'a str, DataValue<'a>)> = map
158 .iter()
159 .map(|(key, value)| {
160 let interned_key = arena.intern_str(key);
161 let data_value = value_converter(value, arena);
162 (interned_key, data_value)
163 })
164 .collect();
165
166 DataValue::object(arena, &entries)
168}
169
170#[cfg(test)]
171mod tests {
172 use super::*;
173 use serde_json::json;
174
175 #[test]
176 fn test_json_conversion() {
177 let arena = DataArena::new();
178
179 let json = json!({
181 "null": null,
182 "bool": true,
183 "integer": 42,
184 "float": 3.14,
185 "string": "hello",
186 "array": [1, 2, 3],
187 "object": {
188 "a": 1,
189 "b": "two"
190 }
191 });
192
193 let data_value = DataValue::from_json(&json, &arena);
195
196 let json2 = data_value.to_json();
198
199 assert_eq!(json, json2);
201 }
202
203 #[test]
204 fn test_hash_map_conversion() {
205 let arena = DataArena::new();
206
207 let mut map = HashMap::new();
209 map.insert("a".to_string(), 1);
210 map.insert("b".to_string(), 2);
211 map.insert("c".to_string(), 3);
212
213 let data_value = hash_map_to_data_value(&map, &arena, |v, _| DataValue::integer(*v));
215
216 if let DataValue::Object(entries) = data_value {
218 assert_eq!(entries.len(), 3);
219
220 let mut found_a = false;
222 let mut found_b = false;
223 let mut found_c = false;
224
225 for (key, value) in entries.iter() {
226 let v = value.as_i64().unwrap();
227
228 match *key {
229 "a" => {
230 assert_eq!(v, 1);
231 found_a = true;
232 }
233 "b" => {
234 assert_eq!(v, 2);
235 found_b = true;
236 }
237 "c" => {
238 assert_eq!(v, 3);
239 found_c = true;
240 }
241 _ => panic!("Unexpected key: {}", key),
242 }
243 }
244
245 assert!(
246 found_a && found_b && found_c,
247 "Not all expected keys were found"
248 );
249 } else {
250 panic!("Expected DataValue::Object");
251 }
252 }
253
254 #[test]
255 fn test_json_to_data_value() {
256 let arena = DataArena::new();
257
258 let json = json!({
260 "name": "John",
261 "age": 30,
262 "is_active": true
263 });
264
265 let data_value = json_to_data_value(&json, &arena);
267
268 assert!(data_value.is_object());
270 let obj = data_value.as_object().unwrap();
271
272 let mut found_name = false;
274 let mut found_age = false;
275 let mut found_is_active = false;
276
277 for (key, value) in obj.iter() {
278 match *key {
279 "name" => {
280 assert_eq!(value.as_str(), Some("John"));
281 found_name = true;
282 }
283 "age" => {
284 assert_eq!(value.as_i64(), Some(30));
285 found_age = true;
286 }
287 "is_active" => {
288 assert_eq!(value.as_bool(), Some(true));
289 found_is_active = true;
290 }
291 _ => panic!("Unexpected key: {}", key),
292 }
293 }
294
295 assert!(
296 found_name && found_age && found_is_active,
297 "Not all expected keys were found"
298 );
299 }
300
301 #[test]
302 fn test_data_value_to_json() {
303 let arena = DataArena::new();
304
305 let data_value = DataValue::object(
307 &arena,
308 &[
309 (arena.intern_str("name"), DataValue::string(&arena, "Alice")),
310 (
311 arena.intern_str("scores"),
312 DataValue::array(
313 &arena,
314 &[
315 DataValue::integer(95),
316 DataValue::integer(87),
317 DataValue::integer(92),
318 ],
319 ),
320 ),
321 ],
322 );
323
324 let json = data_value_to_json(&data_value);
326
327 if let JsonValue::Object(map) = json {
329 assert_eq!(map.len(), 2);
330
331 if let Some(JsonValue::String(name)) = map.get("name") {
333 assert_eq!(name, "Alice");
334 } else {
335 panic!("Expected 'name' to be a string");
336 }
337
338 if let Some(JsonValue::Array(scores)) = map.get("scores") {
340 assert_eq!(scores.len(), 3);
341 assert_eq!(scores[0], JsonValue::Number(95.into()));
342 assert_eq!(scores[1], JsonValue::Number(87.into()));
343 assert_eq!(scores[2], JsonValue::Number(92.into()));
344 } else {
345 panic!("Expected 'scores' to be an array");
346 }
347 } else {
348 panic!("Expected a JSON object");
349 }
350 }
351
352 #[test]
353 fn test_hash_map_to_data_value_with_complex_values() {
354 let arena = DataArena::new();
355
356 let mut map = HashMap::new();
358 map.insert("user1".to_string(), ("Alice", 25));
359 map.insert("user2".to_string(), ("Bob", 30));
360
361 let data_value = hash_map_to_data_value(&map, &arena, |&(name, age), arena| {
363 DataValue::object(
364 arena,
365 &[
366 (arena.intern_str("name"), DataValue::string(arena, name)),
367 (arena.intern_str("age"), DataValue::integer(age)),
368 ],
369 )
370 });
371
372 if let DataValue::Object(entries) = data_value {
374 assert_eq!(entries.len(), 2);
375
376 for (key, value) in entries.iter() {
378 match *key {
379 "user1" => {
380 if let DataValue::Object(user_entries) = value {
381 let mut found_name = false;
382 let mut found_age = false;
383
384 for (user_key, user_value) in user_entries.iter() {
385 match *user_key {
386 "name" => {
387 assert_eq!(user_value.as_str(), Some("Alice"));
388 found_name = true;
389 }
390 "age" => {
391 assert_eq!(user_value.as_i64(), Some(25));
392 found_age = true;
393 }
394 _ => panic!("Unexpected user key: {}", user_key),
395 }
396 }
397
398 assert!(
399 found_name && found_age,
400 "Not all expected user fields were found"
401 );
402 } else {
403 panic!("Expected user1 to be an object");
404 }
405 }
406 "user2" => {
407 if let DataValue::Object(user_entries) = value {
408 let mut found_name = false;
409 let mut found_age = false;
410
411 for (user_key, user_value) in user_entries.iter() {
412 match *user_key {
413 "name" => {
414 assert_eq!(user_value.as_str(), Some("Bob"));
415 found_name = true;
416 }
417 "age" => {
418 assert_eq!(user_value.as_i64(), Some(30));
419 found_age = true;
420 }
421 _ => panic!("Unexpected user key: {}", user_key),
422 }
423 }
424
425 assert!(
426 found_name && found_age,
427 "Not all expected user fields were found"
428 );
429 } else {
430 panic!("Expected user2 to be an object");
431 }
432 }
433 _ => panic!("Unexpected key: {}", key),
434 }
435 }
436 } else {
437 panic!("Expected DataValue::Object");
438 }
439 }
440}