1#[macro_export(local_inner_macros)]
55macro_rules! json {
56 (true) => {
62 $crate::Value::new_bool(true)
63 };
64
65 (false) => {
66 $crate::Value::new_bool(false)
67 };
68
69 (null) => {
70 $crate::Value::new_null()
71 };
72
73 ([]) => {
74 $crate::Array::new().into_value()
75 };
76
77 ({}) => {
78 $crate::Object::new().into_value()
79 };
80
81 ($($json:tt)+) => {
83 json_internal!($($json)+)
84 };
85}
86
87#[macro_export(local_inner_macros)]
102macro_rules! array {
103 () => {
104 $crate::value::Array::new()
105 };
106
107 ($($tt:tt)+) => {
108 {
109 let value = json_internal!([$($tt)+]);
110 value.into_array().expect("the literal is not a json array")
111 }
112 };
113}
114
115#[macro_export(local_inner_macros)]
135macro_rules! object {
136 () => {
137 $crate::value::Object::new()
138 };
139
140 ($($tt:tt)+) => {
141 {
142 let value = json_internal!({$($tt)+});
143 value.into_object().expect("the literal is not a json object")
144 }
145 };
146}
147
148#[macro_export(local_inner_macros)]
149#[doc(hidden)]
150macro_rules! json_internal {
151 (@array [$($elems:expr,)*]) => {
160 json_internal_array![$($elems)*]
161 };
162
163 (@array [$($elems:expr),*]) => {
165 json_internal_array![$($elems)*]
166 };
167
168 (@array [$($elems:expr,)*] null $($rest:tt)*) => {
170 json_internal!(@array [$($elems,)* json_internal!(null)] $($rest)*)
171 };
172
173 (@array [$($elems:expr,)*] true $($rest:tt)*) => {
175 json_internal!(@array [$($elems,)* json_internal!(true)] $($rest)*)
176 };
177
178 (@array [$($elems:expr,)*] false $($rest:tt)*) => {
180 json_internal!(@array [$($elems,)* json_internal!(false)] $($rest)*)
181 };
182
183 (@array [$($elems:expr,)*] [$($array:tt)*] $($rest:tt)*) => {
185 json_internal!(@array [$($elems,)* json_internal!([$($array)*])] $($rest)*)
186 };
187
188 (@array [$($elems:expr,)*] {$($map:tt)*} $($rest:tt)*) => {
190 json_internal!(@array [$($elems,)* json_internal!({$($map)*})] $($rest)*)
191 };
192
193 (@array [$($elems:expr,)*] $next:expr, $($rest:tt)*) => {
195 json_internal!(@array [$($elems,)* json_internal!($next),] $($rest)*)
196 };
197
198 (@array [$($elems:expr,)*] $last:expr) => {
200 json_internal!(@array [$($elems,)* json_internal!($last)])
201 };
202
203 (@array [$($elems:expr),*] , $($rest:tt)*) => {
205 json_internal!(@array [$($elems,)*] $($rest)*)
206 };
207
208 (@array [$($elems:expr),*] $unexpected:tt $($rest:tt)*) => {
210 json_unexpected!($unexpected)
211 };
212
213 (@object $object:ident () () ()) => {};
225
226 (@object $object:ident [$($key:tt)+] ($value:expr) , $($rest:tt)*) => {
228 let key: &str = ($($key)+).as_ref();
229 let _ = $object.insert(key, $value);
230 json_internal!(@object $object () ($($rest)*) ($($rest)*));
231 };
232
233 (@object $object:ident [$($key:tt)+] ($value:expr) $unexpected:tt $($rest:tt)*) => {
235 json_unexpected!($unexpected);
236 };
237
238 (@object $object:ident [$($key:tt)+] ($value:expr)) => {
240 let key: &str = ($($key)+).as_ref();
241 let _ = $object.insert(key, $value);
242 };
243
244 (@object $object:ident ($($key:tt)+) (: null $($rest:tt)*) $copy:tt) => {
246 json_internal!(@object $object [$($key)+] (json_internal!(null)) $($rest)*);
247 };
248
249 (@object $object:ident ($($key:tt)+) (: true $($rest:tt)*) $copy:tt) => {
251 json_internal!(@object $object [$($key)+] (json_internal!(true)) $($rest)*);
252 };
253
254 (@object $object:ident ($($key:tt)+) (: false $($rest:tt)*) $copy:tt) => {
256 json_internal!(@object $object [$($key)+] (json_internal!(false)) $($rest)*);
257 };
258
259 (@object $object:ident ($($key:tt)+) (: [$($array:tt)*] $($rest:tt)*) $copy:tt) => {
261 json_internal!(@object $object [$($key)+] (json_internal!([$($array)*])) $($rest)*);
262 };
263
264 (@object $object:ident ($($key:tt)+) (: {$($map:tt)*} $($rest:tt)*) $copy:tt) => {
266 json_internal!(@object $object [$($key)+] (json_internal!({$($map)*})) $($rest)*);
267 };
268
269 (@object $object:ident ($($key:tt)+) (: $value:expr , $($rest:tt)*) $copy:tt) => {
271 json_internal!(@object $object [$($key)+] (json_internal!($value)) , $($rest)*);
272 };
273
274 (@object $object:ident ($($key:tt)+) (: $value:expr) $copy:tt) => {
276 json_internal!(@object $object [$($key)+] (json_internal!($value)));
277 };
278
279 (@object $object:ident ($($key:tt)+) (:) $copy:tt) => {
281 json_internal!();
283 };
284
285 (@object $object:ident ($($key:tt)+) () $copy:tt) => {
288 json_internal!();
290 };
291
292 (@object $object:ident () (: $($rest:tt)*) ($colon:tt $($copy:tt)*)) => {
294 json_unexpected!($colon);
296 };
297
298 (@object $object:ident ($($key:tt)*) (, $($rest:tt)*) ($comma:tt $($copy:tt)*)) => {
300 json_unexpected!($comma);
302 };
303
304 (@object $object:ident () (($key:expr) : $($rest:tt)*) $copy:tt) => {
307 json_internal!(@object $object ($key) (: $($rest)*) (: $($rest)*));
308 };
309
310 (@object $object:ident ($($key:tt)*) (: $($unexpected:tt)+) $copy:tt) => {
312 json_expect_expr_comma!($($unexpected)+);
313 };
314
315 (@object $object:ident ($($key:tt)*) ($tt:tt $($rest:tt)*) $copy:tt) => {
317 json_internal!(@object $object ($($key)* $tt) ($($rest)*) ($($rest)*));
318 };
319
320 (true) => {
327 $crate::Value::new_bool(true)
328 };
329
330 (false) => {
331 $crate::Value::new_bool(false)
332 };
333
334 (null) => {
335 $crate::Value::new_null()
336 };
337
338 ([]) => {
339 $crate::Value::new_array()
340 };
341
342 ([ $($tt:tt)+ ]) => {
343 json_internal!(@array [] $($tt)+)
344 };
345
346 ({}) => {
347 $crate::Value::new_object()
348 };
349
350 ({ $($tt:tt)+ }) => {
351 {
352 let mut obj_value = $crate::Value::new_object_with(8);
353 json_internal!(@object obj_value () ($($tt)+) ($($tt)+));
354 obj_value
355 }
356 };
357
358 ($other:expr) => {
361 $crate::value::to_value(&$other).unwrap()
362 };
363}
364
365#[macro_export(local_inner_macros)]
369#[doc(hidden)]
370macro_rules! json_internal_array {
371 ($($content:tt)*) => {
372 {
373 let mut arr_value = $crate::Value::new_array_with(8);
374 $(
375 arr_value.append_value($content);
376 )*
377 arr_value
378 }
379 };
380}
381
382#[macro_export]
383#[doc(hidden)]
384macro_rules! json_unexpected {
385 () => {};
386}
387
388#[macro_export]
389#[doc(hidden)]
390macro_rules! json_expect_expr_comma {
391 ($e:expr , $($tt:tt)*) => {};
392}
393
394#[cfg(test)]
395mod test {
396 use std::collections::HashMap;
397
398 use crate::value::value_trait::JsonValueTrait;
399
400 #[test]
401 fn test_json_macro() {
402 assert!(json!(true).is_true());
403 assert!(json!(false).is_false());
404 assert!(json!(null).is_null());
405 assert!(json!("123").is_str());
406 assert!(json!(vec![1]).is_array());
407 assert_eq!(json!(vec![1, 2, 3][2]).as_i64(), Some(3));
408
409 let buf = json!([1, 2, 3]);
410 let arr = json!([true, false, null, 1, 2, 3, "hi", 1 == 2, buf[1] == buf[2]]);
411 assert!(arr.is_array());
412 assert!(arr[arr.len() - 1].is_false());
413
414 let key = "i";
415 let key2 = "\"i\"";
416 let obj = json!({
417 "a": true,
418 "b": false,
419 "c": null,
420 "array": vec![1, 2, 3],
421 "map": ({
422 let mut map = HashMap::<String, String>::new();
423 map.insert("a".to_string(), "b".to_string());
424 map
425 }),
426 "f": 2.333,
427 "g": "hi",
428 "h": 1 == 2,
429 key: {
430 key2: [buf[1] == buf[2], 1],
431 },
432 });
433 assert!(obj.is_object());
434 assert!(obj["a"].is_true());
435 assert!(obj["array"][0].as_u64().unwrap() == 1);
436 assert!(obj["map"]["a"].as_str().unwrap() == "b");
437 assert!(obj[key][key2][1].as_u64().unwrap() == 1);
438
439 let obj = json!({
440 "a": { "b" : {"c": [[[]], {}, {}]} }
441 });
442 assert!(obj["a"]["b"]["c"][0][0].is_array());
443 }
444
445 #[test]
446 fn test_array_macro() {
447 let arr = array![true, false, null, 1, 2, 3, "hi", 1 == 2];
448 assert!(arr[arr.len() - 1].is_false());
449
450 let buf = array![1, 2, 3];
451 let arr = array![true, false, null, 1, 2, 3, "hi", 1 == 2, buf[1] == buf[2]];
452 assert!(arr[arr.len() - 1].is_false());
453 }
454
455 #[test]
456 fn test_object_macro() {
457 let obj = object! {
458 "a": true,
459 "b": false,
460 "c": null,
461 "d": 1,
462 "e": 2,
463 "f": 3,
464 "g": "hi",
465 "h": 1 == 2,
466 };
467 assert!(obj["a"].is_true());
468
469 let arr = array![1, 2, 3];
470 let obj = object! {
471 "a": true,
472 "b": false,
473 "c": null,
474 "d": 1,
475 "e": 2,
476 "f": 3,
477 "g": "hi",
478 "h": 1 == 2,
479 "i": {
480 "i": [arr[1] == arr[2], 1],
481 },
482 };
483 assert!(obj["i"]["i"][1].as_u64().unwrap() == 1);
484 }
485}