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, the format can be configured in the
Context with a BytesFormat). 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::set_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");§Raw Values
RawJson holds the JSON text of a value. The JSON of values that are
deserialized from JSON is kept as it is: it’s validated but not
deserialized, which is faster, and written out again unchanged. With
the Borrowed adapter the text is
borrowed from the input:
use std::collections::BTreeMap;
use deser::adapters::Borrowed;
use deser_json::RawJson;
#[derive(deser::Deserialize, deser::Serialize)]
struct Envelope<'a> {
kind: String,
#[deser(as = Borrowed)]
payload: RawJson<'a>,
}
let input = r#"{"kind": "point", "payload": {"x": 1.50, "y": 2}}"#;
let envelope: Envelope = deser_json::from_str(input).unwrap();
assert_eq!(envelope.payload.get(), r#"{"x": 1.50, "y": 2}"#);
// deserialized later, once it's known what it is
let point: BTreeMap<String, f64> = envelope.payload.deserialize().unwrap();
assert_eq!(point["x"], 1.5);
// and written out again unchanged
assert_eq!(
deser_json::to_string(&envelope).unwrap(),
r#"{"kind":"point","payload":{"x": 1.50, "y": 2}}"#
);The text is only kept for values in places where the type is known
before the value starts: fields of derived structs, standard containers,
Option and Box. Everywhere else (like the fields of untagged enums)
and for values of other formats (including the other JSON dialects) the
value is encoded as JSON. Other formats serialize the value a
RawJson holds. See Raw for more
information.
§Pretty Printing
By default the output is compact. SerializerConfig::set_pretty indents
it and writes spaces after separators:
use deser_json::{Indent, SerializerConfig};
const PRETTY: SerializerConfig =
SerializerConfig::builder().pretty(Indent::Spaces(2)).build();
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::set_indent and SerializerConfig::set_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::set_inline).
§JSON Lines
By default only whitespace may follow a value. What may follow is
controlled by DeserializerConfig::set_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::builder().trailing(Trailing::Newline).build();
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::set_trailing:
use deser_json::{Serializer, SerializerConfig, Trailing};
const LINES: SerializerConfig =
SerializerConfig::builder().trailing(Trailing::Newline).build();
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::builder().trailing(Trailing::Newline).build();
const WRITE_LINES: SerializerConfig =
SerializerConfig::builder().trailing(Trailing::Newline).build();
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
Structs§
- Deserializer
- Deserializes a serializable from JSON.
- Deserializer
Config - Configures how JSON is deserialized.
- Deserializer
Config Builder - Builds a
DeserializerConfig. - Iter
- An iterator over the values of a JSON stream.
- Json
- The JSON format of
RawJsonvalues. - Serializer
- Serializes values into JSON.
- Serializer
Config - Configures how values are serialized to JSON.
- Serializer
Config Builder - Builds a
SerializerConfig. - Stream
Deserializer - Reads a stream of JSON values (see
deser::stream).
Enums§
- Indent
- How the output is indented.
- Inline
Policy - 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.
Type Aliases§
- RawJson
- JSON text of a value.