1use std::ops::Index;
7
8#[derive(Debug, Clone, PartialEq, Default)]
10pub enum JsonValue {
11 #[default]
13 Null,
14 Bool(bool),
16 Integer(i64),
18 Float(f64),
20 String(String),
22 Array(Vec<JsonValue>),
24 Object(Vec<(String, JsonValue)>),
26}
27
28impl JsonValue {
29 #[inline]
31 pub fn is_null(&self) -> bool {
32 matches!(self, JsonValue::Null)
33 }
34
35 #[inline]
37 pub fn is_bool(&self) -> bool {
38 matches!(self, JsonValue::Bool(_))
39 }
40
41 #[inline]
43 pub fn is_number(&self) -> bool {
44 matches!(self, JsonValue::Integer(_) | JsonValue::Float(_))
45 }
46
47 #[inline]
49 pub fn is_integer(&self) -> bool {
50 matches!(self, JsonValue::Integer(_))
51 }
52
53 #[inline]
55 pub fn is_float(&self) -> bool {
56 matches!(self, JsonValue::Float(_))
57 }
58
59 #[inline]
61 pub fn is_string(&self) -> bool {
62 matches!(self, JsonValue::String(_))
63 }
64
65 #[inline]
67 pub fn is_array(&self) -> bool {
68 matches!(self, JsonValue::Array(_))
69 }
70
71 #[inline]
73 pub fn is_object(&self) -> bool {
74 matches!(self, JsonValue::Object(_))
75 }
76
77 #[inline]
79 pub fn as_bool(&self) -> Option<bool> {
80 match self {
81 JsonValue::Bool(b) => Some(*b),
82 _ => None,
83 }
84 }
85
86 #[inline]
88 pub fn as_i64(&self) -> Option<i64> {
89 match self {
90 JsonValue::Integer(n) => Some(*n),
91 JsonValue::Float(f) => Some(*f as i64),
92 _ => None,
93 }
94 }
95
96 #[inline]
98 pub fn as_u64(&self) -> Option<u64> {
99 match self {
100 JsonValue::Integer(n) if *n >= 0 => Some(*n as u64),
101 JsonValue::Float(f) if *f >= 0.0 => Some(*f as u64),
102 _ => None,
103 }
104 }
105
106 #[inline]
108 pub fn as_f64(&self) -> Option<f64> {
109 match self {
110 JsonValue::Float(f) => Some(*f),
111 JsonValue::Integer(n) => Some(*n as f64),
112 _ => None,
113 }
114 }
115
116 #[inline]
118 pub fn as_str(&self) -> Option<&str> {
119 match self {
120 JsonValue::String(s) => Some(s),
121 _ => None,
122 }
123 }
124
125 #[inline]
127 pub fn as_array(&self) -> Option<&[JsonValue]> {
128 match self {
129 JsonValue::Array(arr) => Some(arr),
130 _ => None,
131 }
132 }
133
134 #[inline]
136 pub fn as_array_mut(&mut self) -> Option<&mut Vec<JsonValue>> {
137 match self {
138 JsonValue::Array(arr) => Some(arr),
139 _ => None,
140 }
141 }
142
143 #[inline]
145 pub fn as_object(&self) -> Option<&[(String, JsonValue)]> {
146 match self {
147 JsonValue::Object(obj) => Some(obj),
148 _ => None,
149 }
150 }
151
152 #[inline]
154 pub fn as_object_mut(&mut self) -> Option<&mut Vec<(String, JsonValue)>> {
155 match self {
156 JsonValue::Object(obj) => Some(obj),
157 _ => None,
158 }
159 }
160
161 #[inline]
163 pub fn get(&self, key: &str) -> Option<&JsonValue> {
164 match self {
165 JsonValue::Object(obj) => obj.iter().find(|(k, _)| k == key).map(|(_, v)| v),
166 _ => None,
167 }
168 }
169
170 #[inline]
172 pub fn get_index(&self, index: usize) -> Option<&JsonValue> {
173 match self {
174 JsonValue::Array(arr) => arr.get(index),
175 _ => None,
176 }
177 }
178
179 #[inline]
181 pub fn get_mut(&mut self, key: &str) -> Option<&mut JsonValue> {
182 match self {
183 JsonValue::Object(obj) => obj.iter_mut().find(|(k, _)| k == key).map(|(_, v)| v),
184 _ => None,
185 }
186 }
187
188 #[inline]
190 pub fn into_string(self) -> Option<String> {
191 match self {
192 JsonValue::String(s) => Some(s),
193 _ => None,
194 }
195 }
196
197 #[inline]
199 pub fn into_array(self) -> Option<Vec<JsonValue>> {
200 match self {
201 JsonValue::Array(arr) => Some(arr),
202 _ => None,
203 }
204 }
205
206 #[inline]
208 pub fn into_object(self) -> Option<Vec<(String, JsonValue)>> {
209 match self {
210 JsonValue::Object(obj) => Some(obj),
211 _ => None,
212 }
213 }
214}
215
216static NULL: JsonValue = JsonValue::Null;
218
219impl Index<&str> for JsonValue {
220 type Output = JsonValue;
221
222 fn index(&self, key: &str) -> &Self::Output {
223 self.get(key).unwrap_or(&NULL)
224 }
225}
226
227impl Index<usize> for JsonValue {
228 type Output = JsonValue;
229
230 fn index(&self, index: usize) -> &Self::Output {
231 self.get_index(index).unwrap_or(&NULL)
232 }
233}
234
235impl From<bool> for JsonValue {
236 fn from(v: bool) -> Self {
237 JsonValue::Bool(v)
238 }
239}
240
241impl From<i32> for JsonValue {
242 fn from(v: i32) -> Self {
243 JsonValue::Integer(v as i64)
244 }
245}
246
247impl From<i64> for JsonValue {
248 fn from(v: i64) -> Self {
249 JsonValue::Integer(v)
250 }
251}
252
253impl From<u32> for JsonValue {
254 fn from(v: u32) -> Self {
255 JsonValue::Integer(v as i64)
256 }
257}
258
259impl From<u64> for JsonValue {
260 fn from(v: u64) -> Self {
261 JsonValue::Integer(v as i64)
262 }
263}
264
265impl From<f32> for JsonValue {
266 fn from(v: f32) -> Self {
267 JsonValue::Float(v as f64)
268 }
269}
270
271impl From<f64> for JsonValue {
272 fn from(v: f64) -> Self {
273 JsonValue::Float(v)
274 }
275}
276
277impl From<String> for JsonValue {
278 fn from(v: String) -> Self {
279 JsonValue::String(v)
280 }
281}
282
283impl From<&str> for JsonValue {
284 fn from(v: &str) -> Self {
285 JsonValue::String(v.to_string())
286 }
287}
288
289impl<T: Into<JsonValue>> From<Vec<T>> for JsonValue {
290 fn from(v: Vec<T>) -> Self {
291 JsonValue::Array(v.into_iter().map(Into::into).collect())
292 }
293}
294
295impl<T: Into<JsonValue>> From<Option<T>> for JsonValue {
296 fn from(v: Option<T>) -> Self {
297 match v {
298 Some(v) => v.into(),
299 None => JsonValue::Null,
300 }
301 }
302}
303
304#[cfg(test)]
305mod tests {
306 use super::*;
307
308 #[test]
309 fn test_is_methods() {
310 assert!(JsonValue::Null.is_null());
311 assert!(JsonValue::Bool(true).is_bool());
312 assert!(JsonValue::Integer(42).is_integer());
313 assert!(JsonValue::Float(3.14).is_float());
314 assert!(JsonValue::String("test".into()).is_string());
315 assert!(JsonValue::Array(vec![]).is_array());
316 assert!(JsonValue::Object(vec![]).is_object());
317 }
318
319 #[test]
320 fn test_as_methods() {
321 assert_eq!(JsonValue::Bool(true).as_bool(), Some(true));
322 assert_eq!(JsonValue::Integer(42).as_i64(), Some(42));
323 assert_eq!(JsonValue::Float(3.14).as_f64(), Some(3.14));
324 assert_eq!(JsonValue::String("test".into()).as_str(), Some("test"));
325 }
326
327 #[test]
328 fn test_index_object() {
329 let obj = JsonValue::Object(vec![
330 ("name".into(), JsonValue::String("test".into())),
331 ("value".into(), JsonValue::Integer(42)),
332 ]);
333
334 assert_eq!(obj["name"].as_str(), Some("test"));
335 assert_eq!(obj["value"].as_i64(), Some(42));
336 assert!(obj["missing"].is_null());
337 }
338
339 #[test]
340 fn test_index_array() {
341 let arr = JsonValue::Array(vec![
342 JsonValue::Integer(1),
343 JsonValue::Integer(2),
344 JsonValue::Integer(3),
345 ]);
346
347 assert_eq!(arr[0].as_i64(), Some(1));
348 assert_eq!(arr[1].as_i64(), Some(2));
349 assert!(arr[10].is_null());
350 }
351}