1
- //! 
1
+ //! 
2
2
//!
3
3
//! # json-rust
4
4
//!
38
38
//! "#).unwrap();
39
39
//!
40
40
//! let instantiated = object!{
41
- //! "code" => 200,
42
- //! "success" => true,
43
- //! "payload" => object!{
44
- //! "features" => array![
41
+ //! // quotes on keys are optional
42
+ //! "code": 200,
43
+ //! success: true,
44
+ //! payload: {
45
+ //! features: [
45
46
//! "awesome",
46
47
//! "easyAPI",
47
48
//! "lowLearningCurve"
61
62
//! # #[macro_use] extern crate json;
62
63
//! # fn main() {
63
64
//! let mut data = object!{
64
- //! " foo" => false,
65
- //! " bar" => json::Null ,
66
- //! " answer" => 42,
67
- //! " list" => array![json::Null , "world", true]
65
+ //! foo: false,
66
+ //! bar: null ,
67
+ //! answer: 42,
68
+ //! list: [null , "world", true]
68
69
//! };
69
70
//!
70
71
//! // Partial equality is implemented for most raw types:
174
175
//! ```
175
176
//! # #[macro_use] extern crate json;
176
177
//! # fn main() {
177
- //! let data = array!["foo", "bar", 100, true, json::Null ];
178
+ //! let data = array!["foo", "bar", 100, true, null ];
178
179
//! assert_eq!(data.dump(), r#"["foo","bar",100,true,null]"#);
179
180
//! # }
180
181
//! ```
185
186
//! # #[macro_use] extern crate json;
186
187
//! # fn main() {
187
188
//! let data = object!{
188
- //! " name" => "John Doe",
189
- //! " age" => 30,
190
- //! " canJSON" => true
189
+ //! name: "John Doe",
190
+ //! age: 30,
191
+ //! canJSON: true
191
192
//! };
192
193
//! assert_eq!(
193
194
//! data.dump(),
@@ -279,16 +280,65 @@ pub fn stringify_pretty<T>(root: T, spaces: u16) -> String where T: Into<JsonVal
279
280
macro_rules! array {
280
281
[ ] => ( $crate:: JsonValue :: new_array( ) ) ;
281
282
282
- [ $( $item: expr ) ,* ] => ( {
283
- let size = 0 $( + { let _ = $item; 1 } ) * ;
283
+ // Handles for token tree items
284
+ [ @ITEM ( $( $i: expr, ) * ) $item: tt, $( $cont: tt ) +] => {
285
+ $crate:: array!(
286
+ @ITEM ( $( $i, ) * $crate:: value!( $item) , )
287
+ $( $cont ) *
288
+ )
289
+ } ;
290
+ ( @ITEM ( $( $i: expr, ) * ) $item: tt, ) => ( {
291
+ $crate:: array!( @END $( $i, ) * $crate:: value!( $item) , )
292
+ } ) ;
293
+ ( @ITEM ( $( $i: expr, ) * ) $item: tt) => ( {
294
+ $crate:: array!( @END $( $i, ) * $crate:: value!( $item) , )
295
+ } ) ;
296
+
297
+ // Handles for expression items
298
+ [ @ITEM ( $( $i: expr, ) * ) $item: expr, $( $cont: tt ) +] => {
299
+ $crate:: array!(
300
+ @ITEM ( $( $i, ) * $crate:: value!( $item) , )
301
+ $( $cont ) *
302
+ )
303
+ } ;
304
+ ( @ITEM ( $( $i: expr, ) * ) $item: expr, ) => ( {
305
+ $crate:: array!( @END $( $i, ) * $crate:: value!( $item) , )
306
+ } ) ;
307
+ ( @ITEM ( $( $i: expr, ) * ) $item: expr) => ( {
308
+ $crate:: array!( @END $( $i, ) * $crate:: value!( $item) , )
309
+ } ) ;
310
+
311
+ // Construct the actual array
312
+ ( @END $( $i: expr, ) * ) => ( {
313
+ let size = 0 $( + { let _ = || $i; 1 } ) * ;
284
314
let mut array = Vec :: with_capacity( size) ;
285
315
286
316
$(
287
- array. push( $item . into( ) ) ;
317
+ array. push( $i . into( ) ) ;
288
318
) *
289
319
290
320
$crate:: JsonValue :: Array ( array)
291
- } )
321
+ } ) ;
322
+
323
+ // Entry point to the macro
324
+ ( $( $cont: tt ) +) => {
325
+ $crate:: array!( @ITEM ( ) $( $cont) * )
326
+ } ;
327
+ }
328
+
329
+ #[ macro_export]
330
+ /// Helper crate for converting types into `JsonValue`. It's used
331
+ /// internally by the `object!` and `array!` macros.
332
+ macro_rules! value {
333
+ ( null ) => { $crate:: Null } ;
334
+ ( [ $( $token: tt ) * ] ) => {
335
+ // 10
336
+ $crate:: array![ $( $token ) * ]
337
+ } ;
338
+ ( { $( $token: tt ) * } ) => {
339
+ $crate:: object!{ $( $token ) * }
340
+ } ;
341
+ { $value: expr } => { $value } ;
292
342
}
293
343
294
344
/// Helper macro for creating instances of `JsonValue::Object`.
@@ -297,8 +347,8 @@ macro_rules! array {
297
347
/// # #[macro_use] extern crate json;
298
348
/// # fn main() {
299
349
/// let data = object!{
300
- /// " foo" => 42,
301
- /// " bar" => false
350
+ /// foo: 42,
351
+ /// bar: false,
302
352
/// };
303
353
///
304
354
/// assert_eq!(data["foo"], 42);
@@ -312,29 +362,68 @@ macro_rules! object {
312
362
// Empty object.
313
363
{ } => ( $crate:: JsonValue :: new_object( ) ) ;
314
364
315
- // Non-empty object, no trailing comma.
316
- //
317
- // In this implementation, key/value pairs separated by commas.
318
- { $( $key: expr => $value: expr ) ,* } => {
319
- $crate:: object!( $(
320
- $key => $value,
321
- ) * )
365
+ // Handles for different types of keys
366
+ ( @ENTRY ( $( $k: expr => $v: expr, ) * ) $key: ident: $( $cont: tt ) * ) => {
367
+ $crate:: object!( @ENTRY ( $( $k => $v, ) * ) stringify!( $key) => $( $cont) * )
322
368
} ;
369
+ ( @ENTRY ( $( $k: expr => $v: expr, ) * ) $key: literal: $( $cont: tt ) * ) => {
370
+ $crate:: object!( @ENTRY ( $( $k => $v, ) * ) $key => $( $cont) * )
371
+ } ;
372
+ ( @ENTRY ( $( $k: expr => $v: expr, ) * ) [ $key: expr] : $( $cont: tt ) * ) => {
373
+ $crate:: object!( @ENTRY ( $( $k => $v, ) * ) $key => $( $cont) * )
374
+ } ;
375
+
376
+ // Handles for token tree values
377
+ ( @ENTRY ( $( $k: expr => $v: expr, ) * ) $key: expr => $value: tt, $( $cont: tt ) +) => {
378
+ $crate:: object!(
379
+ @ENTRY ( $( $k => $v, ) * $key => $crate:: value!( $value) , )
380
+ $( $cont ) *
381
+ )
382
+ } ;
383
+ ( @ENTRY ( $( $k: expr => $v: expr, ) * ) $key: expr => $value: tt, ) => ( {
384
+ $crate:: object!( @END $( $k => $v, ) * $key => $crate:: value!( $value) , )
385
+ } ) ;
386
+ ( @ENTRY ( $( $k: expr => $v: expr, ) * ) $key: expr => $value: tt) => ( {
387
+ $crate:: object!( @END $( $k => $v, ) * $key => $crate:: value!( $value) , )
388
+ } ) ;
389
+
390
+ // Handles for expression values
391
+ ( @ENTRY ( $( $k: expr => $v: expr, ) * ) $key: expr => $value: expr, $( $cont: tt ) +) => {
392
+ $crate:: object!(
393
+ @ENTRY ( $( $k => $v, ) * $key => $crate:: value!( $value) , )
394
+ $( $cont ) *
395
+ )
396
+ } ;
397
+ ( @ENTRY ( $( $k: expr => $v: expr, ) * ) $key: expr => $value: expr, ) => ( {
398
+ $crate:: object!( @END $( $k => $v, ) * $key => $crate:: value!( $value) , )
399
+ } ) ;
323
400
324
- // Non-empty object, trailing comma.
325
- //
326
- // In this implementation, the comma is part of the value.
327
- { $( $key: expr => $value: expr, ) * } => ( {
328
- use $crate:: object:: Object ;
401
+ ( @ENTRY ( $( $k: expr => $v: expr, ) * ) $key: expr => $value: expr) => ( {
402
+ $crate:: object!( @END $( $k => $v, ) * $key => $crate:: value!( $value) , )
403
+ } ) ;
329
404
330
- let size = 0 $( + { let _ = $key; 1 } ) * ;
331
- let mut object = Object :: with_capacity( size) ;
405
+ // Construct the actual object
406
+ ( @END $( $k: expr => $v: expr, ) * ) => ( {
407
+ let size = 0 $( + { let _ = || $k; 1 } ) * ;
408
+ let mut object = $crate:: object:: Object :: with_capacity( size) ;
332
409
333
410
$(
334
- object. insert( $key , $value . into( ) ) ;
411
+ object. insert( $k , $v . into( ) ) ;
335
412
) *
336
413
337
414
$crate:: JsonValue :: Object ( object)
338
- } )
339
- }
415
+ } ) ;
416
+
417
+ // Entry point to the macro
418
+ ( $key: tt: $( $cont: tt ) +) => {
419
+ $crate:: object!( @ENTRY ( ) $key: $( $cont) * )
420
+ } ;
340
421
422
+ // Legacy macro
423
+ ( $( $k: expr => $v: expr, ) * ) => {
424
+ $crate:: object!( @END $( $k => $crate:: value!( $v) , ) * )
425
+ } ;
426
+ ( $( $k: expr => $v: expr ) ,* ) => {
427
+ $crate:: object!( @END $( $k => $crate:: value!( $v) , ) * )
428
+ } ;
429
+ }
0 commit comments