nson/
json.rs

1//! Json
2
3use alloc::string::String;
4use alloc::vec::Vec;
5
6use serde_json::{self, Map, json};
7
8use base64::{Engine, engine::general_purpose};
9
10use crate::array::Array;
11use crate::id::Id;
12use crate::map::Map as NsonMap;
13use crate::value::Value;
14
15impl From<Value> for serde_json::Value {
16    fn from(value: Value) -> Self {
17        match value {
18            Value::F32(v) => json!(v),
19            Value::F64(v) => json!({"$f64": v}),
20            Value::I32(v) => json!(v),
21            Value::I64(v) => json!({"$i64": v}),
22            Value::U32(v) => json!({"$u32": v}),
23            Value::U64(v) => json!({"$u64": v}),
24            Value::I8(v) => json!({"$i8": v}),
25            Value::U8(v) => json!({"$u8": v}),
26            Value::I16(v) => json!({"$i16": v}),
27            Value::U16(v) => json!({"$u16": v}),
28            Value::String(v) => json!(v),
29            Value::Array(v) => {
30                let array: Vec<serde_json::Value> = v.into_iter().map(|v| v.into()).collect();
31                json!(array)
32            }
33            Value::Map(v) => {
34                let map: Map<String, serde_json::Value> =
35                    v.into_iter().map(|(k, v)| (k, v.into())).collect();
36                json!(map)
37            }
38            Value::Bool(v) => json!(v),
39            Value::Null => json!(null),
40            Value::Binary(v) => json!({"$bin": general_purpose::STANDARD.encode(v.0)}),
41            Value::TimeStamp(v) => json!({"$tim": v.0}),
42            Value::Id(v) => json!({"$mid": v.to_hex()}),
43        }
44    }
45}
46
47impl From<serde_json::Value> for Value {
48    fn from(value: serde_json::Value) -> Self {
49        match value {
50            serde_json::Value::Number(v) => {
51                if let Some(i) = v.as_i64() {
52                    Value::I32(i as i32)
53                } else if let Some(u) = v.as_u64() {
54                    Value::I32(u as i32)
55                } else if let Some(f) = v.as_f64() {
56                    Value::F32(f as f32)
57                } else {
58                    unreachable!()
59                }
60            }
61            serde_json::Value::String(v) => v.into(),
62            serde_json::Value::Bool(v) => v.into(),
63            serde_json::Value::Array(v) => {
64                let array: Vec<Value> = v.into_iter().map(|v| v.into()).collect();
65                Value::Array(Array::from_vec(array))
66            }
67            serde_json::Value::Object(map) => {
68                if map.len() == 1 {
69                    let keys: Vec<_> = map.keys().map(|s| s.as_str()).collect();
70
71                    match keys.as_slice() {
72                        ["$tim"] => {
73                            if let Some(v) = map.get("$tim")
74                                && let Some(u) = v.as_u64()
75                            {
76                                return Value::TimeStamp(u.into());
77                            }
78                        }
79                        ["$bin"] => {
80                            if let Some(v) = map.get("$bin")
81                                && let Some(hex) = v.as_str()
82                                && let Ok(bin) = general_purpose::STANDARD.decode(hex)
83                            {
84                                return bin.into();
85                            }
86                        }
87                        ["$mid"] => {
88                            if let Some(v) = map.get("$mid")
89                                && let Some(hex) = v.as_str()
90                                && let Ok(message_id) = Id::with_string(hex)
91                            {
92                                return message_id.into();
93                            }
94                        }
95                        ["$f64"] => {
96                            if let Some(v) = map.get("$f64")
97                                && let Some(f) = v.as_f64()
98                            {
99                                return Value::F64(f);
100                            }
101                        }
102                        ["$i64"] => {
103                            if let Some(v) = map.get("$i64")
104                                && let Some(i) = v.as_i64()
105                            {
106                                return Value::I64(i);
107                            }
108                        }
109                        ["$u32"] => {
110                            if let Some(v) = map.get("$u32")
111                                && let Some(u) = v.as_u64()
112                            {
113                                return Value::U32(u as u32);
114                            }
115                        }
116                        ["$u64"] => {
117                            if let Some(v) = map.get("$u64")
118                                && let Some(u) = v.as_u64()
119                            {
120                                return Value::U64(u);
121                            }
122                        }
123                        ["$i8"] => {
124                            if let Some(v) = map.get("$i8")
125                                && let Some(i) = v.as_i64()
126                            {
127                                return Value::I8(i as i8);
128                            }
129                        }
130                        ["$u8"] => {
131                            if let Some(v) = map.get("$u8")
132                                && let Some(u) = v.as_u64()
133                            {
134                                return Value::U8(u as u8);
135                            }
136                        }
137                        ["$i16"] => {
138                            if let Some(v) = map.get("$i16")
139                                && let Some(i) = v.as_i64()
140                            {
141                                return Value::I16(i as i16);
142                            }
143                        }
144                        ["$u16"] => {
145                            if let Some(v) = map.get("$u16")
146                                && let Some(u) = v.as_u64()
147                            {
148                                return Value::U16(u as u16);
149                            }
150                        }
151                        _ => (),
152                    }
153                }
154
155                let map: NsonMap = map.into_iter().map(|(k, v)| (k, v.into())).collect();
156
157                Value::Map(map)
158            }
159            serde_json::Value::Null => Value::Null,
160        }
161    }
162}
163
164impl From<NsonMap> for serde_json::Value {
165    fn from(map: NsonMap) -> Self {
166        Value::Map(map).into()
167    }
168}
169
170impl From<serde_json::Value> for NsonMap {
171    fn from(json: serde_json::Value) -> Self {
172        let value: Value = json.into();
173
174        match value {
175            Value::Map(map) => map,
176            _ => NsonMap::new(),
177        }
178    }
179}
180
181#[cfg(test)]
182mod test {
183    use crate::{Id, TimeStamp, Value, m};
184    use serde_json::{self, json};
185
186    use crate::__vec;
187
188    #[test]
189    fn convert_json() {
190        let json = json!({
191            "a": 1i32,
192            "b": {"$i64": 2i64},
193            "c": {"$u32": 3u32},
194            "d": {"$u64": 4u64},
195            "e": 5.6f32,
196            "f": {"$f64": 7.8f64},
197            "g": {
198                "$tim": 456
199            },
200            "h": {
201                "$mid": "0171253e54db9aef760d5fbd"
202            },
203            "i": {
204                "$bin": "AQIDBAUG"
205            }
206        });
207
208        let message = m! {
209            "a": 1i32,
210            "b": 2i64,
211            "c": 3u32,
212            "d": 4u64,
213            "e": 5.6f32,
214            "f": 7.8f64,
215            "g": TimeStamp(456),
216            "h": Id::with_string("0171253e54db9aef760d5fbd").unwrap(),
217            "i": __vec![1u8, 2, 3, 4, 5, 6]
218        };
219
220        let nson_value: Value = message.clone().into();
221
222        let value: serde_json::Value = message.into();
223
224        assert!(json == value);
225
226        let value2: Value = json.into();
227
228        assert!(nson_value == value2);
229    }
230}