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;