1- //! 
1+ //! 
22//!
33//! # json-rust
44//!
3838//! "#).unwrap();
3939//!
4040//! 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: [
4546//! "awesome",
4647//! "easyAPI",
4748//! "lowLearningCurve"
6162//! # #[macro_use] extern crate json;
6263//! # fn main() {
6364//! 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]
6869//! };
6970//!
7071//! // Partial equality is implemented for most raw types:
174175//! ```
175176//! # #[macro_use] extern crate json;
176177//! # fn main() {
177- //! let data = array!["foo", "bar", 100, true, json::Null ];
178+ //! let data = array!["foo", "bar", 100, true, null ];
178179//! assert_eq!(data.dump(), r#"["foo","bar",100,true,null]"#);
179180//! # }
180181//! ```
185186//! # #[macro_use] extern crate json;
186187//! # fn main() {
187188//! let data = object!{
188- //! " name" => "John Doe",
189- //! " age" => 30,
190- //! " canJSON" => true
189+ //! name: "John Doe",
190+ //! age: 30,
191+ //! canJSON: true
191192//! };
192193//! assert_eq!(
193194//! data.dump(),
@@ -279,16 +280,65 @@ pub fn stringify_pretty<T>(root: T, spaces: u16) -> String where T: Into<JsonVal
279280macro_rules! array {
280281 [ ] => ( $crate:: JsonValue :: new_array( ) ) ;
281282
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 } ) * ;
284314 let mut array = Vec :: with_capacity( size) ;
285315
286316 $(
287- array. push( $item . into( ) ) ;
317+ array. push( $i . into( ) ) ;
288318 ) *
289319
290320 $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 } ;
292342}
293343
294344/// Helper macro for creating instances of `JsonValue::Object`.
@@ -297,8 +347,8 @@ macro_rules! array {
297347/// # #[macro_use] extern crate json;
298348/// # fn main() {
299349/// let data = object!{
300- /// " foo" => 42,
301- /// " bar" => false
350+ /// foo: 42,
351+ /// bar: false,
302352/// };
303353///
304354/// assert_eq!(data["foo"], 42);
@@ -312,29 +362,68 @@ macro_rules! object {
312362 // Empty object.
313363 { } => ( $crate:: JsonValue :: new_object( ) ) ;
314364
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) * )
322368 } ;
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+ } ) ;
323400
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+ } ) ;
329404
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) ;
332409
333410 $(
334- object. insert( $key , $value . into( ) ) ;
411+ object. insert( $k , $v . into( ) ) ;
335412 ) *
336413
337414 $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+ } ;
340421
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