Skip to main content

Crate deser_json

Crate deser_json 

Source
Expand description

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.

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:

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, Decimal and 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 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 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) use the text. See DeserializerConfig::exact_numbers.

Strings without escape sequences are borrowed from the input, so types can borrow them:

#[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:

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 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 (also known as NDJSON) one by one:

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:

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 with from_reader and written to a 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 (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:

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), 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. Requires std.
  • speedups: uses simdutf8 to validate UTF-8 when parsing byte slices. Implies zmij.
  • std (enabled by default): uses the standard library. Without it this crate only needs alloc (see no_std).
  • zmij (enabled by default): formats floats with zmij, which is faster and makes binaries smaller. Without it floats are formatted with the same text by a fallback on top of the float formatting of core.

Structs§

Deserializer
Deserializes a serializable from JSON.
DeserializerConfig
Configures how JSON is deserialized.
Iter
An iterator over the values of a JSON stream.
Serializer
Serializes values into JSON.
SerializerConfig
Configures how values are serialized to JSON.
StreamDeserializer
Reads a stream of JSON values (see deser::stream).

Enums§

Indent
How the output is indented.
InlinePolicy
When maps and sequences are written on a single line in indented output.
Trailing
Controls what may follow a value.

Functions§

from_reader
Deserializes a value from a reader.
from_slice
Deserializes JSON from the given bytes.
from_str
Deserializes JSON from the given string.
to_string
Serializes a value to JSON.
to_writer
Serializes a value to a writer.