Skip to main content

deser_json/
lib.rs

1//! Parse and serialize JSON compatible with deser.
2//!
3//! This library is very bare bones at this point and not at all optimized.  It is
4//! based on microserde which in turn is based on miniserde to achieve the most
5//! minimal implementation of a serializer and serializer.
6//!
7//! ```rust
8//! let vec: Vec<u64> = deser_json::from_str("[1, 2, 3, 4]").unwrap();
9//! let json = deser_json::to_string(&vec).unwrap();
10//! assert_eq!(json, "[1,2,3,4]");
11//! ```
12//!
13//! Besides strings, JSON can also be parsed from byte slices with
14//! [`from_slice`].  In that case the input is validated as UTF-8 while it is
15//! parsed rather than upfront:
16//!
17//! ```rust
18//! let vec: Vec<String> = deser_json::from_slice(b"[\"a\", \"b\"]").unwrap();
19//! assert_eq!(vec, ["a", "b"]);
20//! assert!(deser_json::from_slice::<String>(b"\"\xff\"").is_err());
21//! ```
22//!
23//! Integers that do not fit into 64 bits as well as the well-known
24//! [`BigInt`](deser_core::ext::BigInt), [`Decimal`](deser_core::ext::Decimal) and
25//! [`Number`](deser_core::ext::Number) types are written as JSON numbers.  Other
26//! well-known types (such as date-times and UUIDs) are written as strings.
27//! JSON has no bytes, they are written as base64 strings by default and
28//! types that expect bytes accept strings and arrays of integers (see
29//! [bytes](deser_core::adapters#bytes) and [`SerializerConfig::bytes`]).  Floats
30//! are written with the shortest text that reads back as the same value of
31//! their precision (`0.1f32` as `0.1`, not `0.10000000149011612`), floats
32//! that are infinite or NaN as `null`.
33//!
34//! When parsing, floats whose text cannot be recovered from their value as
35//! `f64` (like `0.10` or `1e5`) and integers that do not fit into 128 bits
36//! are passed on as [`Number`](deser_core::ext::Number) which carries the text of
37//! the number and its value as `f64`.  Types like `f64` get the value, types
38//! which deserialize decimal numbers exactly (like
39//! [`Decimal`](deser_core::ext::Decimal)) use the text.  See
40//! [`DeserializerConfig::exact_numbers`].
41//!
42//! Strings without escape sequences are borrowed from the input, so types
43//! can borrow them:
44//!
45//! ```rust
46//! #[derive(deser::Deserialize)]
47//! struct User<'a> {
48//!     name: &'a str,
49//! }
50//!
51//! let user: User = deser_json::from_str(r#"{"name": "Peter"}"#).unwrap();
52//! assert_eq!(user.name, "Peter");
53//! ```
54//!
55//! # Pretty Printing
56//!
57//! By default the output is compact.  [`SerializerConfig::pretty`] indents
58//! it and writes spaces after separators:
59//!
60//! ```rust
61//! use deser_json::{Indent, SerializerConfig};
62//!
63//! const PRETTY: SerializerConfig =
64//!     SerializerConfig::new().pretty(Indent::Spaces(2));
65//! let json = PRETTY.to_string(&vec![vec![1, 2]]).unwrap();
66//! assert_eq!(json, "[\n  [\n    1,\n    2\n  ]\n]");
67//! ```
68//!
69//! Indentation and spaces can also be configured on their own with
70//! [`SerializerConfig::indent`] and [`SerializerConfig::compact`].  Maps
71//! and sequences with the [`Layout::Compact`](deser_core::hints::Layout) hint
72//! are written on a single line in indented output, short ones that only
73//! contain scalars can be too (see [`SerializerConfig::inline`]).
74//!
75//! # JSON Lines
76//!
77//! By default only whitespace may follow a value.  What may follow is
78//! controlled by [`DeserializerConfig::trailing`] (see [`Trailing`]).  With
79//! [`Trailing::Newline`] a [`Deserializer`] reads
80//! [JSON Lines](https://jsonlines.org/) (also known as NDJSON) one by one:
81//!
82//! ```rust
83//! use deser_json::{Deserializer, DeserializerConfig, Trailing};
84//!
85//! let config = DeserializerConfig::new().trailing(Trailing::Newline);
86//! let mut de = Deserializer::from_str_with_config("[1, 2]\n[3]\n", &config);
87//! let lines = de.iter::<Vec<u32>>().collect::<Result<Vec<_>, _>>().unwrap();
88//! assert_eq!(lines, [vec![1, 2], vec![3]]);
89//! ```
90//!
91//! Errors only discard their line, so the remaining lines can still be
92//! read.  [`Trailing::Stop`] stops after the value without looking at what
93//! follows.  JSON Lines are written with a [`Serializer`] and
94//! [`SerializerConfig::trailing`]:
95//!
96//! ```rust
97//! use deser_json::{Serializer, SerializerConfig, Trailing};
98//!
99//! const LINES: SerializerConfig =
100//!     SerializerConfig::new().trailing(Trailing::Newline);
101//! let mut serializer = Serializer::with_config(&LINES);
102//! for value in [vec![1, 2], vec![3]] {
103//!     serializer.serialize(&value).unwrap();
104//! }
105//! assert_eq!(serializer.finish(), "[1,2]\n[3]\n");
106//! ```
107//!
108//! # Streams
109//!
110//! Values are read from a [`Read`](std::io::Read) with [`from_reader`]
111//! and written to a [`Write`](std::io::Write) with [`to_writer`].  To read
112//! or write more than one value (for instance JSON Lines from a socket) the
113//! configurations create readers and writers of
114//! [`deser::io`](deser_core::io) ([`DeserializerConfig::reader`] and
115//! [`SerializerConfig::writer`]).  How values are separated depends on the
116//! `trailing` setting of the configurations (see [`Trailing`]).  The reader
117//! only buffers until a value is complete:
118//!
119//! ```rust
120//! # #[cfg(feature = "io")] {
121//! use std::collections::BTreeMap;
122//! use deser_json::{DeserializerConfig, SerializerConfig, Trailing};
123//!
124//! const READ_LINES: DeserializerConfig =
125//!     DeserializerConfig::new().trailing(Trailing::Newline);
126//! const WRITE_LINES: SerializerConfig =
127//!     SerializerConfig::new().trailing(Trailing::Newline);
128//!
129//! let input = &b"{\"id\": 1}\n{\"id\": 2}\n"[..];
130//! let mut reader = READ_LINES.reader(input);
131//! let mut writer = WRITE_LINES.writer(Vec::new());
132//! while let Some(value) = reader.read::<BTreeMap<String, u32>>().unwrap() {
133//!     writer.write(&value).unwrap();
134//! }
135//! assert_eq!(writer.into_inner(), b"{\"id\":1}\n{\"id\":2}\n");
136//! # }
137//! ```
138//!
139//! The stream serializer ([`Serializer`]) and the stream deserializer
140//! ([`StreamDeserializer`]) do not do IO themselves (see
141//! [`deser::stream`](deser_core::stream)), they also work with other kinds
142//! of IO (for instance async runtimes with `deser-tokio`) and without the
143//! standard library.
144//!
145//! # Features
146//!
147//! * `io` (enabled by default): reading and writing streams of the
148//!   standard library, see [streams](#streams).  Requires `std`.
149//! * `speedups`: uses the `zmij` crate for float formatting and
150//!   `simdutf8` to validate UTF-8 when parsing byte slices.  Otherwise this
151//!   crate has no dependencies other than `deser`.
152//! * `std` (enabled by default): uses the standard library.  Without it
153//!   this crate only needs `alloc` (see [`no_std`](https://docs.rs/deser/latest/deser/#no_std)).
154#![doc(html_logo_url = "https://raw.githubusercontent.com/mitsuhiko/deser/main/artwork/logo.svg")]
155#![cfg_attr(not(any(feature = "std", test)), no_std)]
156
157extern crate alloc;
158
159mod buf;
160mod escape;
161mod pretty;
162mod ser;
163mod trailing;
164
165// These are generated from `deser-template-json`.
166mod de;
167mod parser;
168mod scan;
169mod stream;
170
171pub use self::de::{Deserializer, DeserializerConfig, Iter, from_slice, from_str};
172#[cfg(feature = "io")]
173pub use self::ser::to_writer;
174pub use self::ser::{Indent, InlinePolicy, Serializer, SerializerConfig, to_string};
175pub use self::stream::StreamDeserializer;
176#[cfg(feature = "io")]
177pub use self::stream::from_reader;
178pub use self::trailing::Trailing;