1use linkrs_core::{List, Value};
10
11pub fn to_json(value: Value) -> serde_json::Value {
13 match value {
14 Value::Empty => serde_json::Value::Null,
15 Value::Null(_) => serde_json::Value::Null,
16 Value::Bool(b) => serde_json::Value::Bool(b),
17 Value::SmallInt(i) => serde_json::Value::Number(i.into()),
18 Value::Int(i) => serde_json::Value::Number(i.into()),
19 Value::BigInt(i) => serde_json::Value::Number(i.into()),
20 Value::Float(f) => serde_json::Value::Number(
21 serde_json::Number::from_f64(f as f64).unwrap_or(serde_json::Number::from(0)),
22 ),
23 Value::Double(f) => serde_json::Value::Number(
24 serde_json::Number::from_f64(f).unwrap_or(serde_json::Number::from(0)),
25 ),
26 Value::Decimal128(d) => serde_json::Value::String(d.to_string()),
27 Value::String(s) => serde_json::Value::String(s.to_string()),
28 Value::FixedString(data) => serde_json::Value::String(data.to_string()),
29 Value::Blob(blob) => serde_json::Value::String(format!("{:?}", blob)),
30 Value::Date(d) => serde_json::Value::String(d.to_string()),
31 Value::Time(t) => serde_json::Value::String(t.to_string()),
32 Value::DateTime(dt) => serde_json::Value::String(dt.to_string()),
33 Value::Vertex(v) => serde_json::json!(v),
34 Value::Edge(e) => serde_json::json!(e),
35 Value::EdgeHeader(h) => serde_json::json!(h),
36 Value::Path(p) => serde_json::json!(p),
37 Value::List(list) => serde_json::Value::Array(list.into_iter().map(to_json).collect()),
38 Value::Map(map) => {
39 let obj: serde_json::Map<String, serde_json::Value> = map
40 .into_iter()
41 .map(|(k, v)| (format!("{}", k), to_json(v)))
42 .collect();
43 serde_json::Value::Object(obj)
44 }
45 Value::Set(set) => serde_json::Value::Array(set.into_iter().map(to_json).collect()),
46 Value::Geography(g) => serde_json::json!(g),
47 Value::Vector(v) => {
48 let arr = v
49 .to_dense()
50 .iter()
51 .map(|&f| {
52 serde_json::Number::from_f64(f as f64).unwrap_or(serde_json::Number::from(0))
53 })
54 .collect::<Vec<_>>();
55 serde_json::Value::Array(arr.into_iter().map(serde_json::Value::Number).collect())
56 }
57 Value::DataSet(ds) => serde_json::json!(ds),
58 Value::Json(j) => serde_json::from_str(j.as_str()).unwrap_or(serde_json::Value::Null),
59 Value::JsonB(j) => j.as_value().clone(),
60 Value::Uuid(u) => serde_json::Value::String(u.to_hyphenated_string()),
61 Value::Interval(i) => serde_json::Value::String(i.to_postgresql()),
62 Value::VertexId(vid) => serde_json::Value::String(format!("{:?}", vid)),
63 Value::EdgeId(eid) => serde_json::Value::String(format!("{:?}", eid)),
64 Value::Struct(s) => {
65 let obj: serde_json::Map<String, serde_json::Value> =
66 s.fields.into_iter().map(|(k, v)| (k, to_json(v))).collect();
67 serde_json::Value::Object(obj)
68 }
69 Value::Array(a) => serde_json::Value::Array(a.values.into_iter().map(to_json).collect()),
70 }
71}
72
73pub fn from_json(value: &serde_json::Value) -> Value {
76 match value {
77 serde_json::Value::Null => Value::Null(Default::default()),
78 serde_json::Value::Bool(b) => Value::Bool(*b),
79 serde_json::Value::Number(n) => {
80 if let Some(i) = n.as_i64() {
81 Value::BigInt(i)
82 } else if let Some(u) = n.as_u64() {
83 Value::BigInt(u as i64)
84 } else {
85 Value::Double(n.as_f64().unwrap_or(0.0))
86 }
87 }
88 serde_json::Value::String(s) => Value::string(s.as_str()),
89 serde_json::Value::Array(items) => {
90 Value::list(List::from_vec(items.iter().map(from_json).collect()))
91 }
92 serde_json::Value::Object(map) => Value::Map(Box::new(
93 map.iter()
94 .map(|(k, v)| (Value::string(k.clone()), from_json(v)))
95 .collect(),
96 )),
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103 use linkrs_core::types::DataType;
104
105 #[test]
106 fn scalars_encode() {
107 assert_eq!(to_json(Value::Bool(true)), serde_json::json!(true));
108 assert_eq!(to_json(Value::Int(7)), serde_json::json!(7));
109 assert_eq!(to_json(Value::BigInt(-9)), serde_json::json!(-9));
110 assert_eq!(to_json(Value::Double(1.5)), serde_json::json!(1.5));
111 assert_eq!(to_json(Value::string("hi")), serde_json::json!("hi"));
112 assert_eq!(
113 to_json(Value::Null(Default::default())),
114 serde_json::Value::Null
115 );
116 assert_eq!(to_json(Value::Empty), serde_json::Value::Null);
117 }
118
119 #[test]
120 fn list_and_map_encode() {
121 let list = Value::list(List::from_vec(vec![Value::Int(1), Value::Int(2)]));
122 assert_eq!(to_json(list), serde_json::json!([1, 2]));
123
124 let map: Value = Value::Map(Box::new(
125 [(Value::string("a"), Value::BigInt(1))]
126 .into_iter()
127 .collect(),
128 ));
129 assert_eq!(to_json(map), serde_json::json!({"a": 1}));
130 }
131
132 #[test]
133 fn scalar_roundtrip() {
134 let cases = vec![
135 serde_json::json!(null),
136 serde_json::json!(true),
137 serde_json::json!(42),
138 serde_json::json!(-7),
139 serde_json::json!(3.25),
140 serde_json::json!("text"),
141 ];
142 for case in cases {
143 let core = from_json(&case);
144 let back = to_json(core);
145 assert_eq!(back, case);
146 }
147 }
148
149 #[test]
150 fn list_roundtrip() {
151 let case = serde_json::json!([1, "two", false, null]);
152 let core = from_json(&case);
153 assert!(matches!(core, Value::List(_)));
154 assert_eq!(to_json(core), case);
155 }
156
157 #[test]
158 fn map_roundtrip() {
159 let case = serde_json::json!({"a": 1, "b": [true]});
160 let core = from_json(&case);
161 assert!(matches!(core, Value::Map(_)));
162 assert_eq!(to_json(core), case);
163 }
164
165 #[test]
166 fn data_type_display_is_wire_format() {
167 assert_eq!(DataType::Bool.to_string(), "BOOL");
168 }
169}