deser-json 0.9.0

JSON support for deser
Documentation
//! Parse and serialize JSON compatible with deser.
//!
//! This library is very bare bones at this point and not at all optimized.  It is
//! based on microserde which in turn is based on miniserde to achieve the most
//! minimal implementation of a serializer and serializer.
//!
//! ```rust
//! let vec: Vec<u64> = deser_json::from_str("[1, 2, 3, 4]").unwrap();
//! let json = deser_json::to_string(&vec).unwrap();
//! assert_eq!(json, "[1,2,3,4]");
//! ```
//!
//! Besides strings, JSON can also be parsed from byte slices with
//! [`from_slice`].  In that case the input is validated as UTF-8 while it is
//! parsed rather than upfront:
//!
//! ```rust
//! let vec: Vec<String> = deser_json::from_slice(b"[\"a\", \"b\"]").unwrap();
//! assert_eq!(vec, ["a", "b"]);
//! assert!(deser_json::from_slice::<String>(b"\"\xff\"").is_err());
//! ```
//!
//! Integers that do not fit into 64 bits as well as the well-known
//! [`BigInt`](deser_core::ext::BigInt), [`Decimal`](deser_core::ext::Decimal) and
//! [`Number`](deser_core::ext::Number) types are written as JSON numbers.  Other
//! well-known types (such as date-times and UUIDs) are written as strings.
//! JSON has no bytes, they are written as base64 strings by default and
//! types that expect bytes accept strings and arrays of integers (see
//! [bytes](deser_core::adapters#bytes) and [`SerializerConfig::bytes`]).  Floats
//! are written with the shortest text that reads back as the same value of
//! their precision (`0.1f32` as `0.1`, not `0.10000000149011612`), floats
//! that are infinite or NaN as `null`.
//!
//! When parsing, floats whose text cannot be recovered from their value as
//! `f64` (like `0.10` or `1e5`) and integers that do not fit into 128 bits
//! are passed on as [`Number`](deser_core::ext::Number) which carries the text of
//! the number and its value as `f64`.  Types like `f64` get the value, types
//! which deserialize decimal numbers exactly (like
//! [`Decimal`](deser_core::ext::Decimal)) use the text.  See
//! [`DeserializerConfig::exact_numbers`].
//!
//! Strings without escape sequences are borrowed from the input, so types
//! can borrow them:
//!
//! ```rust
//! #[derive(deser::Deserialize)]
//! struct User<'a> {
//!     name: &'a str,
//! }
//!
//! let user: User = deser_json::from_str(r#"{"name": "Peter"}"#).unwrap();
//! assert_eq!(user.name, "Peter");
//! ```
//!
//! # Pretty Printing
//!
//! By default the output is compact.  [`SerializerConfig::pretty`] indents
//! it and writes spaces after separators:
//!
//! ```rust
//! use deser_json::{Indent, SerializerConfig};
//!
//! const PRETTY: SerializerConfig =
//!     SerializerConfig::new().pretty(Indent::Spaces(2));
//! let json = PRETTY.to_string(&vec![vec![1, 2]]).unwrap();
//! assert_eq!(json, "[\n  [\n    1,\n    2\n  ]\n]");
//! ```
//!
//! Indentation and spaces can also be configured on their own with
//! [`SerializerConfig::indent`] and [`SerializerConfig::compact`].  Maps
//! and sequences with the [`Layout::Compact`](deser_core::hints::Layout) hint
//! are written on a single line in indented output, short ones that only
//! contain scalars can be too (see [`SerializerConfig::inline`]).
//!
//! # JSON Lines
//!
//! By default only whitespace may follow a value.  What may follow is
//! controlled by [`DeserializerConfig::trailing`] (see [`Trailing`]).  With
//! [`Trailing::Newline`] a [`Deserializer`] reads
//! [JSON Lines](https://jsonlines.org/) (also known as NDJSON) one by one:
//!
//! ```rust
//! use deser_json::{Deserializer, DeserializerConfig, Trailing};
//!
//! let config = DeserializerConfig::new().trailing(Trailing::Newline);
//! let mut de = Deserializer::from_str_with_config("[1, 2]\n[3]\n", &config);
//! let lines = de.iter::<Vec<u32>>().collect::<Result<Vec<_>, _>>().unwrap();
//! assert_eq!(lines, [vec![1, 2], vec![3]]);
//! ```
//!
//! Errors only discard their line, so the remaining lines can still be
//! read.  [`Trailing::Stop`] stops after the value without looking at what
//! follows.  JSON Lines are written with a [`Serializer`] and
//! [`SerializerConfig::trailing`]:
//!
//! ```rust
//! use deser_json::{Serializer, SerializerConfig, Trailing};
//!
//! const LINES: SerializerConfig =
//!     SerializerConfig::new().trailing(Trailing::Newline);
//! let mut serializer = Serializer::with_config(&LINES);
//! for value in [vec![1, 2], vec![3]] {
//!     serializer.serialize(&value).unwrap();
//! }
//! assert_eq!(serializer.finish(), "[1,2]\n[3]\n");
//! ```
//!
//! # Streams
//!
//! Values are read from a [`Read`](std::io::Read) with [`from_reader`]
//! and written to a [`Write`](std::io::Write) with [`to_writer`].  To read
//! or write more than one value (for instance JSON Lines from a socket) the
//! configurations create readers and writers of
//! [`deser::io`](deser_core::io) ([`DeserializerConfig::reader`] and
//! [`SerializerConfig::writer`]).  How values are separated depends on the
//! `trailing` setting of the configurations (see [`Trailing`]).  The reader
//! only buffers until a value is complete:
//!
//! ```rust
//! # #[cfg(feature = "io")] {
//! use std::collections::BTreeMap;
//! use deser_json::{DeserializerConfig, SerializerConfig, Trailing};
//!
//! const READ_LINES: DeserializerConfig =
//!     DeserializerConfig::new().trailing(Trailing::Newline);
//! const WRITE_LINES: SerializerConfig =
//!     SerializerConfig::new().trailing(Trailing::Newline);
//!
//! let input = &b"{\"id\": 1}\n{\"id\": 2}\n"[..];
//! let mut reader = READ_LINES.reader(input);
//! let mut writer = WRITE_LINES.writer(Vec::new());
//! while let Some(value) = reader.read::<BTreeMap<String, u32>>().unwrap() {
//!     writer.write(&value).unwrap();
//! }
//! assert_eq!(writer.into_inner(), b"{\"id\":1}\n{\"id\":2}\n");
//! # }
//! ```
//!
//! The stream serializer ([`Serializer`]) and the stream deserializer
//! ([`StreamDeserializer`]) do not do IO themselves (see
//! [`deser::stream`](deser_core::stream)), they also work with other kinds
//! of IO (for instance async runtimes with `deser-tokio`) and without the
//! standard library.
//!
//! # Features
//!
//! * `io` (enabled by default): reading and writing streams of the
//!   standard library, see [streams](#streams).  Requires `std`.
//! * `speedups`: uses the `zmij` crate for float formatting and
//!   `simdutf8` to validate UTF-8 when parsing byte slices.  Otherwise this
//!   crate has no dependencies other than `deser`.
//! * `std` (enabled by default): uses the standard library.  Without it
//!   this crate only needs `alloc` (see [`no_std`](https://docs.rs/deser/latest/deser/#no_std)).
#![doc(html_logo_url = "https://raw.githubusercontent.com/mitsuhiko/deser/main/artwork/logo.svg")]
#![cfg_attr(not(any(feature = "std", test)), no_std)]

extern crate alloc;

mod buf;
mod escape;
mod pretty;
mod ser;
mod trailing;

// These are generated from `deser-template-json`.
mod de;
mod parser;
mod scan;
mod stream;

pub use self::de::{Deserializer, DeserializerConfig, Iter, from_slice, from_str};
#[cfg(feature = "io")]
pub use self::ser::to_writer;
pub use self::ser::{Indent, InlinePolicy, Serializer, SerializerConfig, to_string};
pub use self::stream::StreamDeserializer;
#[cfg(feature = "io")]
pub use self::stream::from_reader;
pub use self::trailing::Trailing;