jzon/lib.rs
1//! 
2//!
3//! # json-rust
4//!
5//! Parse and serialize [JSON](http://json.org/) with ease.
6//!
7//! **[Changelog](https://github.com/maciejhirsz/json-rust/releases) -**
8//! **[Complete Documentation](https://docs.rs/json/) -**
9//! **[Cargo](https://crates.io/crates/json) -**
10//! **[Repository](https://github.com/maciejhirsz/json-rust)**
11//!
12//! ## Why?
13//!
14//! JSON is a very loose format where anything goes - arrays can hold mixed
15//! types, object keys can change types between API calls or not include
16//! some keys under some conditions. Mapping that to idiomatic Rust structs
17//! introduces friction.
18//!
19//! This crate intends to avoid that friction.
20//!
21//! ```rust
22//! # #[macro_use] extern crate jzon;
23//! # fn main() {
24//! let parsed = jzon::parse(r#"
25//!
26//! {
27//! "code": 200,
28//! "success": true,
29//! "payload": {
30//! "features": [
31//! "awesome",
32//! "easyAPI",
33//! "lowLearningCurve"
34//! ]
35//! }
36//! }
37//!
38//! "#).unwrap();
39//!
40//! let instantiated = object!{
41//! // quotes on keys are optional
42//! "code": 200,
43//! success: true,
44//! payload: {
45//! features: [
46//! "awesome",
47//! "easyAPI",
48//! "lowLearningCurve"
49//! ]
50//! }
51//! };
52//!
53//! assert_eq!(parsed, instantiated);
54//! # }
55//! ```
56//!
57//! ## First class citizen
58//!
59//! Using macros and indexing, it's easy to work with the data.
60//!
61//! ```rust
62//! # #[macro_use] extern crate jzon;
63//! # fn main() {
64//! let mut data = object!{
65//! foo: false,
66//! bar: null,
67//! answer: 42,
68//! list: [null, "world", true]
69//! };
70//!
71//! // Partial equality is implemented for most raw types:
72//! assert!(data["foo"] == false);
73//!
74//! // And it's type aware, `null` and `false` are different values:
75//! assert!(data["bar"] != false);
76//!
77//! // But you can use any Rust number types:
78//! assert!(data["answer"] == 42);
79//! assert!(data["answer"] == 42.0);
80//! assert!(data["answer"] == 42isize);
81//!
82//! // Access nested structures, arrays and objects:
83//! assert!(data["list"][0].is_null());
84//! assert!(data["list"][1] == "world");
85//! assert!(data["list"][2] == true);
86//!
87//! // Error resilient - accessing properties that don't exist yield null:
88//! assert!(data["this"]["does"]["not"]["exist"].is_null());
89//!
90//! // Mutate by assigning:
91//! data["list"][0] = "Hello".into();
92//!
93//! // Use the `dump` method to serialize the data:
94//! assert_eq!(data.dump(), r#"{"foo":false,"bar":null,"answer":42,"list":["Hello","world",true]}"#);
95//!
96//! // Or pretty print it out:
97//! println!("{:#}", data);
98//! # }
99//! ```
100//!
101//! ## Serialize with `jzon::stringify(value)`
102//!
103//! Primitives:
104//!
105//! ```
106//! // str slices
107//! assert_eq!(jzon::stringify("foobar"), "\"foobar\"");
108//!
109//! // Owned strings
110//! assert_eq!(jzon::stringify("foobar".to_string()), "\"foobar\"");
111//!
112//! // Any number types
113//! assert_eq!(jzon::stringify(42), "42");
114//!
115//! // Booleans
116//! assert_eq!(jzon::stringify(true), "true");
117//! assert_eq!(jzon::stringify(false), "false");
118//! ```
119//!
120//! Explicit `null` type `jzon::Null`:
121//!
122//! ```
123//! assert_eq!(jzon::stringify(jzon::Null), "null");
124//! ```
125//!
126//! Optional types:
127//!
128//! ```
129//! let value: Option<String> = Some("foo".to_string());
130//! assert_eq!(jzon::stringify(value), "\"foo\"");
131//!
132//! let no_value: Option<String> = None;
133//! assert_eq!(jzon::stringify(no_value), "null");
134//! ```
135//!
136//! Vector:
137//!
138//! ```
139//! let data = vec![1,2,3];
140//! assert_eq!(jzon::stringify(data), "[1,2,3]");
141//! ```
142//!
143//! Vector with optional values:
144//!
145//! ```
146//! let data = vec![Some(1), None, Some(2), None, Some(3)];
147//! assert_eq!(jzon::stringify(data), "[1,null,2,null,3]");
148//! ```
149//!
150//! Pushing to arrays:
151//!
152//! ```
153//! let mut data = jzon::JsonValue::new_array();
154//!
155//! data.push(10);
156//! data.push("foo");
157//! data.push(false);
158//!
159//! assert_eq!(data.dump(), r#"[10,"foo",false]"#);
160//! ```
161//!
162//! Putting fields on objects:
163//!
164//! ```
165//! let mut data = jzon::JsonValue::new_object();
166//!
167//! data["answer"] = 42.into();
168//! data["foo"] = "bar".into();
169//!
170//! assert_eq!(data.dump(), r#"{"answer":42,"foo":"bar"}"#);
171//! ```
172//!
173//! `array!` macro:
174//!
175//! ```
176//! # #[macro_use] extern crate jzon;
177//! # fn main() {
178//! let data = array!["foo", "bar", 100, true, null];
179//! assert_eq!(data.dump(), r#"["foo","bar",100,true,null]"#);
180//! # }
181//! ```
182//!
183//! `object!` macro:
184//!
185//! ```
186//! # #[macro_use] extern crate jzon;
187//! # fn main() {
188//! let data = object!{
189//! name: "John Doe",
190//! age: 30,
191//! canJSON: true
192//! };
193//! assert_eq!(
194//! data.dump(),
195//! r#"{"name":"John Doe","age":30,"canJSON":true}"#
196//! );
197//! # }
198//! ```
199
200use std::result;
201
202pub mod codegen;
203mod parser;
204mod value;
205mod error;
206mod util;
207
208pub mod short;
209pub mod object;
210pub mod number;
211
212pub use error::Error;
213pub use value::JsonValue;
214pub use value::JsonValue::Null;
215
216/// Result type used by this crate.
217///
218///
219/// *Note:* Since 0.9.0 the old `JsonResult` type is deprecated. Always use
220/// `jzon::Result` instead.
221pub type Result<T> = result::Result<T, Error>;
222
223pub mod iterators {
224 /// Iterator over members of `JsonValue::Array`.
225 pub type Members<'a> = ::std::slice::Iter<'a, super::JsonValue>;
226
227 /// Mutable iterator over members of `JsonValue::Array`.
228 pub type MembersMut<'a> = ::std::slice::IterMut<'a, super::JsonValue>;
229
230 /// Iterator over key value pairs of `JsonValue::Object`.
231 pub type Entries<'a> = super::object::Iter<'a>;
232
233 /// Mutable iterator over key value pairs of `JsonValue::Object`.
234 pub type EntriesMut<'a> = super::object::IterMut<'a>;
235}
236
237#[deprecated(since="0.9.0", note="use `jzon::Error` instead")]
238pub use Error as JsonError;
239
240#[deprecated(since="0.9.0", note="use `jzon::Result` instead")]
241pub use crate::Result as JsonResult;
242
243pub use parser::parse;
244
245pub type Array = Vec<JsonValue>;
246
247/// Convenience for `JsonValue::from(value)`
248pub fn from<T>(value: T) -> JsonValue where T: Into<JsonValue> {
249 value.into()
250}
251
252/// Pretty prints out the value as JSON string.
253pub fn stringify<T>(root: T) -> String where T: Into<JsonValue> {
254 let root: JsonValue = root.into();
255 root.dump()
256}
257
258/// Pretty prints out the value as JSON string. Second argument is a
259/// number of spaces to indent new blocks with.
260pub fn stringify_pretty<T>(root: T, spaces: u16) -> String where T: Into<JsonValue> {
261 let root: JsonValue = root.into();
262 root.pretty(spaces)
263}
264
265/// Helper macro for creating instances of `JsonValue::Array`.
266///
267/// ```
268/// # #[macro_use] extern crate jzon;
269/// # fn main() {
270/// let data = array!["foo", 42, false];
271///
272/// assert_eq!(data[0], "foo");
273/// assert_eq!(data[1], 42);
274/// assert_eq!(data[2], false);
275///
276/// assert_eq!(data.dump(), r#"["foo",42,false]"#);
277/// # }
278/// ```
279#[macro_export]
280macro_rules! array {
281 [] => ($crate::JsonValue::new_array());
282
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} )*;
314 let mut array = Vec::with_capacity(size);
315
316 $(
317 array.push($i.into());
318 )*
319
320 $crate::JsonValue::Array(array)
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.
332macro_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 };
342}
343
344/// Helper macro for creating instances of `JsonValue::Object`.
345///
346/// ```
347/// # #[macro_use] extern crate jzon;
348/// # fn main() {
349/// let data = object!{
350/// foo: 42,
351/// bar: false,
352/// };
353///
354/// assert_eq!(data["foo"], 42);
355/// assert_eq!(data["bar"], false);
356///
357/// assert_eq!(data.dump(), r#"{"foo":42,"bar":false}"#);
358/// # }
359/// ```
360#[macro_export]
361macro_rules! object {
362 // Empty object.
363 {} => ($crate::JsonValue::new_object());
364
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)*)
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 });
400
401 (@ENTRY($( $k:expr => $v:expr, )*) $key:expr => $value:expr) => ({
402 $crate::object!(@END $( $k => $v, )* $key => $crate::value!($value), )
403 });
404
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);
409
410 $(
411 object.insert($k, $v.into());
412 )*
413
414 $crate::JsonValue::Object(object)
415 });
416
417 // Entry point to the macro
418 ($key:tt: $( $cont:tt )+) => {
419 $crate::object!(@ENTRY() $key: $($cont)*)
420 };
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}