nodedb_types/
conversion.rs1use crate::Value;
8
9fn json_number(n: &serde_json::Number) -> Value {
13 if let Some(i) = n.as_i64() {
14 Value::Integer(i)
15 } else if let Some(u) = n.as_u64() {
16 Value::from_u64(u)
17 } else {
18 n.as_f64().map_or(Value::Null, Value::Float)
19 }
20}
21
22pub fn json_to_value(v: serde_json::Value) -> Value {
26 match v {
27 serde_json::Value::Null => Value::Null,
28 serde_json::Value::Bool(b) => Value::Bool(b),
29 serde_json::Value::Number(n) => json_number(&n),
30 serde_json::Value::String(s) => Value::String(s),
31 serde_json::Value::Array(arr) => Value::Array(arr.into_iter().map(json_to_value).collect()),
32 serde_json::Value::Object(obj) => Value::Object(
33 obj.into_iter()
34 .map(|(k, v)| (k, json_to_value(v)))
35 .collect(),
36 ),
37 }
38}
39
40pub fn json_to_value_ref(v: &serde_json::Value) -> Value {
57 match v {
58 serde_json::Value::Null => Value::Null,
59 serde_json::Value::Bool(b) => Value::Bool(*b),
60 serde_json::Value::Number(n) => json_number(n),
61 serde_json::Value::String(s) => Value::String(s.clone()),
62 serde_json::Value::Array(arr) => Value::Array(arr.iter().map(json_to_value_ref).collect()),
63 serde_json::Value::Object(map) => Value::Object(
64 map.iter()
65 .map(|(k, v)| (k.clone(), json_to_value_ref(v)))
66 .collect(),
67 ),
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn owned_preserves_nested_objects() {
77 let v = serde_json::json!({"a": 1, "b": {"nested": true}});
78 let val = json_to_value(v);
79 match val {
80 Value::Object(map) => {
81 assert_eq!(map.get("a"), Some(&Value::Integer(1)));
82 assert!(matches!(map.get("b"), Some(Value::Object(_))));
83 }
84 _ => panic!("expected Object"),
85 }
86 }
87
88 #[test]
93 fn by_reference_preserves_nested_objects_and_arrays() {
94 let v = serde_json::json!({"a": 1, "b": {"nested": true}, "c": [{"deep": "x"}]});
95 assert_eq!(json_to_value_ref(&v), json_to_value(v.clone()));
96
97 let Value::Object(map) = json_to_value_ref(&v) else {
98 panic!("expected Object");
99 };
100 assert!(matches!(map.get("b"), Some(Value::Object(_))));
101 let Some(Value::Array(items)) = map.get("c") else {
102 panic!("expected Array");
103 };
104 assert!(matches!(items.first(), Some(Value::Object(_))));
105 }
106
107 #[test]
108 fn primitives_roundtrip() {
109 assert_eq!(json_to_value(serde_json::Value::Null), Value::Null);
110 assert_eq!(
111 json_to_value(serde_json::Value::Bool(true)),
112 Value::Bool(true)
113 );
114 assert_eq!(json_to_value(serde_json::json!(42)), Value::Integer(42));
115 let max = serde_json::json!(u64::MAX);
116 let exact = Value::Decimal(rust_decimal::Decimal::from(u64::MAX));
117 assert_eq!(json_to_value_ref(&max), exact);
118 assert_eq!(json_to_value(max), exact);
119 assert_eq!(
120 json_to_value(serde_json::json!("hello")),
121 Value::String("hello".into())
122 );
123 }
124}