1 /// Construct a `serde_json::Value` from a JSON literal.
2 ///
3 /// ```
4 /// # use serde_json::json;
5 /// #
6 /// let value = json!({
7 ///     "code": 200,
8 ///     "success": true,
9 ///     "payload": {
10 ///         "features": [
11 ///             "serde",
12 ///             "json"
13 ///         ]
14 ///     }
15 /// });
16 /// ```
17 ///
18 /// Variables or expressions can be interpolated into the JSON literal. Any type
19 /// interpolated into an array element or object value must implement Serde's
20 /// `Serialize` trait, while any type interpolated into a object key must
21 /// implement `Into<String>`. If the `Serialize` implementation of the
22 /// interpolated type decides to fail, or if the interpolated type contains a
23 /// map with non-string keys, the `json!` macro will panic.
24 ///
25 /// ```
26 /// # use serde_json::json;
27 /// #
28 /// let code = 200;
29 /// let features = vec!["serde", "json"];
30 ///
31 /// let value = json!({
32 ///     "code": code,
33 ///     "success": code == 200,
34 ///     "payload": {
35 ///         features[0]: features[1]
36 ///     }
37 /// });
38 /// ```
39 ///
40 /// Trailing commas are allowed inside both arrays and objects.
41 ///
42 /// ```
43 /// # use serde_json::json;
44 /// #
45 /// let value = json!([
46 ///     "notice",
47 ///     "the",
48 ///     "trailing",
49 ///     "comma -->",
50 /// ]);
51 /// ```
52 #[macro_export(local_inner_macros)]
53 macro_rules! json {
54     // Hide distracting implementation details from the generated rustdoc.
55     ($($json:tt)+) => {
56         json_internal!($($json)+)
57     };
58 }
59 
60 // Rocket relies on this because they export their own `json!` with a different
61 // doc comment than ours, and various Rust bugs prevent them from calling our
62 // `json!` from their `json!` so they call `json_internal!` directly. Check with
63 // @SergioBenitez before making breaking changes to this macro.
64 //
65 // Changes are fine as long as `json_internal!` does not call any new helper
66 // macros and can still be invoked as `json_internal!($($json)+)`.
67 #[macro_export(local_inner_macros)]
68 #[doc(hidden)]
69 macro_rules! json_internal {
70     //////////////////////////////////////////////////////////////////////////
71     // TT muncher for parsing the inside of an array [...]. Produces a vec![...]
72     // of the elements.
73     //
74     // Must be invoked as: json_internal!(@array [] $($tt)*)
75     //////////////////////////////////////////////////////////////////////////
76 
77     // Done with trailing comma.
78     (@array [$($elems:expr,)*]) => {
79         json_internal_vec![$($elems,)*]
80     };
81 
82     // Done without trailing comma.
83     (@array [$($elems:expr),*]) => {
84         json_internal_vec![$($elems),*]
85     };
86 
87     // Next element is `null`.
88     (@array [$($elems:expr,)*] null $($rest:tt)*) => {
89         json_internal!(@array [$($elems,)* json_internal!(null)] $($rest)*)
90     };
91 
92     // Next element is `true`.
93     (@array [$($elems:expr,)*] true $($rest:tt)*) => {
94         json_internal!(@array [$($elems,)* json_internal!(true)] $($rest)*)
95     };
96 
97     // Next element is `false`.
98     (@array [$($elems:expr,)*] false $($rest:tt)*) => {
99         json_internal!(@array [$($elems,)* json_internal!(false)] $($rest)*)
100     };
101 
102     // Next element is an array.
103     (@array [$($elems:expr,)*] [$($array:tt)*] $($rest:tt)*) => {
104         json_internal!(@array [$($elems,)* json_internal!([$($array)*])] $($rest)*)
105     };
106 
107     // Next element is a map.
108     (@array [$($elems:expr,)*] {$($map:tt)*} $($rest:tt)*) => {
109         json_internal!(@array [$($elems,)* json_internal!({$($map)*})] $($rest)*)
110     };
111 
112     // Next element is an expression followed by comma.
113     (@array [$($elems:expr,)*] $next:expr, $($rest:tt)*) => {
114         json_internal!(@array [$($elems,)* json_internal!($next),] $($rest)*)
115     };
116 
117     // Last element is an expression with no trailing comma.
118     (@array [$($elems:expr,)*] $last:expr) => {
119         json_internal!(@array [$($elems,)* json_internal!($last)])
120     };
121 
122     // Comma after the most recent element.
123     (@array [$($elems:expr),*] , $($rest:tt)*) => {
124         json_internal!(@array [$($elems,)*] $($rest)*)
125     };
126 
127     // Unexpected token after most recent element.
128     (@array [$($elems:expr),*] $unexpected:tt $($rest:tt)*) => {
129         json_unexpected!($unexpected)
130     };
131 
132     //////////////////////////////////////////////////////////////////////////
133     // TT muncher for parsing the inside of an object {...}. Each entry is
134     // inserted into the given map variable.
135     //
136     // Must be invoked as: json_internal!(@object $map () ($($tt)*) ($($tt)*))
137     //
138     // We require two copies of the input tokens so that we can match on one
139     // copy and trigger errors on the other copy.
140     //////////////////////////////////////////////////////////////////////////
141 
142     // Done.
143     (@object $object:ident () () ()) => {};
144 
145     // Insert the current entry followed by trailing comma.
146     (@object $object:ident [$($key:tt)+] ($value:expr) , $($rest:tt)*) => {
147         let _ = $object.insert(($($key)+).into(), $value);
148         json_internal!(@object $object () ($($rest)*) ($($rest)*));
149     };
150 
151     // Current entry followed by unexpected token.
152     (@object $object:ident [$($key:tt)+] ($value:expr) $unexpected:tt $($rest:tt)*) => {
153         json_unexpected!($unexpected);
154     };
155 
156     // Insert the last entry without trailing comma.
157     (@object $object:ident [$($key:tt)+] ($value:expr)) => {
158         let _ = $object.insert(($($key)+).into(), $value);
159     };
160 
161     // Next value is `null`.
162     (@object $object:ident ($($key:tt)+) (: null $($rest:tt)*) $copy:tt) => {
163         json_internal!(@object $object [$($key)+] (json_internal!(null)) $($rest)*);
164     };
165 
166     // Next value is `true`.
167     (@object $object:ident ($($key:tt)+) (: true $($rest:tt)*) $copy:tt) => {
168         json_internal!(@object $object [$($key)+] (json_internal!(true)) $($rest)*);
169     };
170 
171     // Next value is `false`.
172     (@object $object:ident ($($key:tt)+) (: false $($rest:tt)*) $copy:tt) => {
173         json_internal!(@object $object [$($key)+] (json_internal!(false)) $($rest)*);
174     };
175 
176     // Next value is an array.
177     (@object $object:ident ($($key:tt)+) (: [$($array:tt)*] $($rest:tt)*) $copy:tt) => {
178         json_internal!(@object $object [$($key)+] (json_internal!([$($array)*])) $($rest)*);
179     };
180 
181     // Next value is a map.
182     (@object $object:ident ($($key:tt)+) (: {$($map:tt)*} $($rest:tt)*) $copy:tt) => {
183         json_internal!(@object $object [$($key)+] (json_internal!({$($map)*})) $($rest)*);
184     };
185 
186     // Next value is an expression followed by comma.
187     (@object $object:ident ($($key:tt)+) (: $value:expr , $($rest:tt)*) $copy:tt) => {
188         json_internal!(@object $object [$($key)+] (json_internal!($value)) , $($rest)*);
189     };
190 
191     // Last value is an expression with no trailing comma.
192     (@object $object:ident ($($key:tt)+) (: $value:expr) $copy:tt) => {
193         json_internal!(@object $object [$($key)+] (json_internal!($value)));
194     };
195 
196     // Missing value for last entry. Trigger a reasonable error message.
197     (@object $object:ident ($($key:tt)+) (:) $copy:tt) => {
198         // "unexpected end of macro invocation"
199         json_internal!();
200     };
201 
202     // Missing colon and value for last entry. Trigger a reasonable error
203     // message.
204     (@object $object:ident ($($key:tt)+) () $copy:tt) => {
205         // "unexpected end of macro invocation"
206         json_internal!();
207     };
208 
209     // Misplaced colon. Trigger a reasonable error message.
210     (@object $object:ident () (: $($rest:tt)*) ($colon:tt $($copy:tt)*)) => {
211         // Takes no arguments so "no rules expected the token `:`".
212         json_unexpected!($colon);
213     };
214 
215     // Found a comma inside a key. Trigger a reasonable error message.
216     (@object $object:ident ($($key:tt)*) (, $($rest:tt)*) ($comma:tt $($copy:tt)*)) => {
217         // Takes no arguments so "no rules expected the token `,`".
218         json_unexpected!($comma);
219     };
220 
221     // Key is fully parenthesized. This avoids clippy double_parens false
222     // positives because the parenthesization may be necessary here.
223     (@object $object:ident () (($key:expr) : $($rest:tt)*) $copy:tt) => {
224         json_internal!(@object $object ($key) (: $($rest)*) (: $($rest)*));
225     };
226 
227     // Refuse to absorb colon token into key expression.
228     (@object $object:ident ($($key:tt)*) (: $($unexpected:tt)+) $copy:tt) => {
229         json_expect_expr_comma!($($unexpected)+);
230     };
231 
232     // Munch a token into the current key.
233     (@object $object:ident ($($key:tt)*) ($tt:tt $($rest:tt)*) $copy:tt) => {
234         json_internal!(@object $object ($($key)* $tt) ($($rest)*) ($($rest)*));
235     };
236 
237     //////////////////////////////////////////////////////////////////////////
238     // The main implementation.
239     //
240     // Must be invoked as: json_internal!($($json)+)
241     //////////////////////////////////////////////////////////////////////////
242 
243     (null) => {
244         $crate::Value::Null
245     };
246 
247     (true) => {
248         $crate::Value::Bool(true)
249     };
250 
251     (false) => {
252         $crate::Value::Bool(false)
253     };
254 
255     ([]) => {
256         $crate::Value::Array(json_internal_vec![])
257     };
258 
259     ([ $($tt:tt)+ ]) => {
260         $crate::Value::Array(json_internal!(@array [] $($tt)+))
261     };
262 
263     ({}) => {
264         $crate::Value::Object($crate::Map::new())
265     };
266 
267     ({ $($tt:tt)+ }) => {
268         $crate::Value::Object({
269             let mut object = $crate::Map::new();
270             json_internal!(@object object () ($($tt)+) ($($tt)+));
271             object
272         })
273     };
274 
275     // Any Serialize type: numbers, strings, struct literals, variables etc.
276     // Must be below every other rule.
277     ($other:expr) => {
278         $crate::to_value(&$other).unwrap()
279     };
280 }
281 
282 // The json_internal macro above cannot invoke vec directly because it uses
283 // local_inner_macros. A vec invocation there would resolve to $crate::vec.
284 // Instead invoke vec here outside of local_inner_macros.
285 #[macro_export]
286 #[doc(hidden)]
287 macro_rules! json_internal_vec {
288     ($($content:tt)*) => {
289         vec![$($content)*]
290     };
291 }
292 
293 #[macro_export]
294 #[doc(hidden)]
295 macro_rules! json_unexpected {
296     () => {};
297 }
298 
299 #[macro_export]
300 #[doc(hidden)]
301 macro_rules! json_expect_expr_comma {
302     ($e:expr , $($tt:tt)*) => {};
303 }
304