Skip to main content

deser_json5/
lib.rs

1//! Parse [JSON5](https://json5.org/) compatible with deser.
2//!
3//! JSON5 extends JSON with syntax from ECMAScript 5.1:
4//!
5//! * `//` and `/* */` comments,
6//! * commas after the last element of sequences and maps,
7//! * map keys which are ECMAScript identifiers (`{name: "api"}`, with
8//!   Unicode letters and `\u` escapes),
9//! * strings in single quotes, escaped line breaks within strings and the
10//!   escapes `\'`, `\v`, `\0` and `\xFF`,
11//! * hexadecimal numbers (those that do not fit into 64 bits are 128 bit
12//!   integers and floats beyond that), numbers with a leading `+` or a
13//!   leading or trailing decimal point, `Infinity` and `NaN`,
14//! * more whitespace characters.
15//!
16//! Otherwise this works like [`deser-json`](https://docs.rs/deser-json):
17//! strings and identifiers without escape sequences are borrowed from the
18//! input and the positions of errors and values refer to the input.  In
19//! [JSON Lines](Trailing::Newline) only line breaks outside of comments and
20//! strings end a value.  The parser passes the [JSON5 test
21//! suite](https://github.com/json5/json5-tests).
22//!
23//! ```rust
24//! #[derive(deser::Deserialize)]
25//! struct Config<'a> {
26//!     name: &'a str,
27//!     ports: Vec<u16>,
28//!     timeout: f64,
29//! }
30//!
31//! let config: Config = deser_json5::from_str(r#"{
32//!     // the name of the service
33//!     name: 'api',
34//!     ports: [0x50, 443,],
35//!     timeout: .5,
36//! }"#).unwrap();
37//! assert_eq!(config.name, "api");
38//! assert_eq!(config.ports, [80, 443]);
39//! assert_eq!(config.timeout, 0.5);
40//! ```
41//!
42//! JSON is valid JSON5, so values are serialized as JSON (with the same
43//! serializer as `deser-json`).  Unlike JSON, JSON5
44//! can represent NaN and infinite floats: [`to_string`] and [`to_writer`]
45//! write them as `NaN`, `Infinity` and `-Infinity` where `deser-json`
46//! writes `null`.  A [`SerializerConfig`] needs
47//! [`set_non_finite_floats`](SerializerConfig::set_non_finite_floats) for this:
48//!
49//! ```rust
50//! use deser_json5::{Indent, SerializerConfig};
51//!
52//! let values = vec![1.5, f64::NAN, f64::NEG_INFINITY];
53//! assert_eq!(deser_json5::to_string(&values).unwrap(), "[1.5,NaN,-Infinity]");
54//!
55//! const PRETTY: SerializerConfig = SerializerConfig::builder()
56//!     .pretty(Indent::Spaces(2))
57//!     .non_finite_floats(true).build();
58//! assert_eq!(
59//!     PRETTY.to_string(&values).unwrap(),
60//!     "[\n  1.5,\n  NaN,\n  -Infinity\n]"
61//! );
62//! ```
63//!
64//! # Raw Values
65//!
66//! [`RawJson5`] holds the JSON5 text of a value.  Like `deser_json::RawJson` it
67//! keeps the text of values that are deserialized from JSON5 as it is
68//! (including comments), other values are encoded as JSON.  The serializer
69//! of this crate writes the text of raw JSON5 values as it is.  See
70//! [`Raw`](deser_core::ext::Raw) for more information.
71//!
72//! # Features
73//!
74//! * `io` (enabled by default): reading and writing streams of the
75//!   standard library (with `DeserializerConfig::reader`).  Requires
76//!   `std`.
77//! * `speedups` (enabled by default): faster UTF-8 validation.
78//! * `std` (enabled by default): uses the standard library.  Without it
79//!   this crate only needs `alloc` (see [`no_std`](https://docs.rs/deser/latest/deser/#no_std)).
80#![doc(html_logo_url = "https://raw.githubusercontent.com/mitsuhiko/deser/main/artwork/logo.svg")]
81#![cfg_attr(not(any(feature = "std", test)), no_std)]
82
83extern crate alloc;
84
85// These are generated from `deser-template-json`.
86mod buf;
87mod copy;
88mod de;
89mod escape;
90mod parser;
91mod pretty;
92mod raw;
93mod scan;
94mod ser;
95mod stream;
96mod trailing;
97
98pub use self::de::{
99    Deserializer, DeserializerConfig, DeserializerConfigBuilder, Iter, from_slice, from_str,
100};
101pub use self::raw::{Json5, RawJson5};
102#[cfg(feature = "io")]
103pub use self::ser::to_writer;
104pub use self::ser::{
105    Indent, InlinePolicy, Serializer, SerializerConfig, SerializerConfigBuilder, to_string,
106};
107pub use self::stream::StreamDeserializer;
108#[cfg(feature = "io")]
109pub use self::stream::from_reader;
110pub use self::trailing::Trailing;