Expand description
This is full-featured modern JSON implementation according to ECMA-404 standard.
This crate allows deserialization of JSON Iterator<u8>
stream into primitive types (bool
, i32
, etc.),
Strings and any other types that implement special trait called TryFromJson, which can be implemented
automatically through #[derive(TryFromJson)]
for your structs and enums.
And serialization back to JSON through DebugToJson trait, that acts like Debug, allowing to
print your objects with println!()
and such. Or through WriteToJson trait that allows to write
to a io::Write
stream.
This crate allows to read whitespece-separated JSON values from stream in sequence. It also allows to pipe blob strings to a writer.
§Installation
In Cargo.toml
of your project add:
[dependencies]
nop-json = "2.0"
§Examples
§Creating Reader object
First need to create a Reader object giving it something that implements Iterator<Item=u8>
.
We can read from a string like this:
use nop_json::Reader;
let mut reader = Reader::new(r#" "a JSON string" "#.bytes());
To read from a file we need to convert std::io::Read
to Iterator<Item=u8>
. We can use read_iter
crate for this.
use std::fs::File;
use read_iter::ReadIter; // also add dependency to Cargo.toml
use nop_json::Reader;
let mut file = ReadIter::new(File::open("/tmp/test.json").unwrap());
let mut reader = Reader::new(&mut file);
See Reader::new() for more details.
§Deserializing simple values
To read JSON values from an input stream, call reader.read()
method, and assign the result to a variable that implements TryFromJson
.
This crate adds implementation of TryFromJson
to many primitive types, Vec
, HashMap
, and more.
use nop_json::Reader;
let mut reader = Reader::new(r#" true 100.5 "Hello" "Infinity" [true, false] "#.bytes());
let the_true: bool = reader.read().unwrap();
let the_hundred_point_five: f32 = reader.read().unwrap();
let the_hello: String = reader.read().unwrap();
let the_infinity: f32 = reader.read().unwrap();
let the_array: Vec<bool> = reader.read().unwrap();
assert_eq!(the_true, true);
assert_eq!(the_hundred_point_five, 100.5);
assert_eq!(the_hello, "Hello");
assert!(the_infinity.is_infinite());
assert_eq!(the_array, vec![true, false]);
§Deserializing any JSON values
We have generic Value type that can hold any JSON node.
use nop_json::{Reader, Value};
use std::convert::TryInto;
let mut reader = Reader::new(r#" true 100.5 "Hello" [true, false] "#.bytes());
let the_true: Value = reader.read().unwrap();
let the_hundred_point_five: Value = reader.read().unwrap();
let the_hello: Value = reader.read().unwrap();
let the_array: Value = reader.read().unwrap();
assert_eq!(the_true, Value::Bool(true));
let the_hundred_point_five: f32 = the_hundred_point_five.try_into().unwrap();
assert_eq!(the_hundred_point_five, 100.5f32);
assert_eq!(the_hello, Value::String("Hello".to_string()));
assert_eq!(the_array, Value::Array(vec![Value::Bool(true), Value::Bool(false)]));
You can parse any JSON document to Value.
use nop_json::{Reader, Value};
let mut reader = Reader::new(r#" {"array": [{"x": 1}, "a string"]} "#.bytes());
let doc: Value = reader.read().unwrap();
assert_eq!(doc.to_string(), r#"{"array":[{"x":1},"a string"]}"#);
§Deserializing/serializing structs and enums
To deserialize a struct or an enum, your struct needs to implement TryFromJson and ValidateJson traits. To serialize - DebugToJson and/or WriteToJson.
use nop_json::{Reader, TryFromJson, ValidateJson, DebugToJson};
#[derive(TryFromJson, ValidateJson, DebugToJson, PartialEq)]
struct Point {x: i32, y: i32}
#[derive(TryFromJson, ValidateJson, DebugToJson, PartialEq)]
enum Geometry
{ #[json(point)] Point(Point),
#[json(cx, cy, r)] Circle(i32, i32, i32),
Nothing,
}
let mut reader = Reader::new(r#" {"point": {"x": 0, "y": 0}} "#.bytes());
let obj: Geometry = reader.read().unwrap();
println!("Serialized back to JSON: {:?}", obj);
See TryFromJson, ValidateJson, DebugToJson, WriteToJson.
§Serializing scalar values
You can println!() word “true” or “false” to serialize a boolean. Also numbers can be printed as println!() does by default. The format is JSON-compatible. To serialize a &str, you can use escape function.
Alternatively you can create a Value object, and serialize with it any scalar/nonscalar value.
use std::convert::TryInto;
use nop_json::Value;
let the_true: Value = true.try_into().unwrap();
println!("Serialized to JSON: {:?}", the_true);
§Skipping a value from stream
To skip current value without storing it (and allocating memory), read it to the ()
type.
use nop_json::Reader;
let mut reader = Reader::new(r#" true 100.5 "Hello" [true, false] "#.bytes());
let _: () = reader.read().unwrap();
let _: () = reader.read().unwrap();
let _: () = reader.read().unwrap();
let _: () = reader.read().unwrap();
§Reading binary data
See read_blob.
§Null, NaN, infinity and -0
Reading to a variable of type Option<T>
can read either T
or null
.
use nop_json::Reader;
let mut reader = Reader::new(r#" "non-null" null "#.bytes());
let str_or_null_1: Option<String> = reader.read().unwrap();
let str_or_null_2: Option<String> = reader.read().unwrap();
assert_eq!(str_or_null_1, Some("non-null".to_string()));
assert_eq!(str_or_null_2, None);
Reading junk to f32
or f64
type will read NaN. Reading string “Infinity”, “-Infinity” and “-0” will read corresponding floating point numbers.
use nop_json::Reader;
let mut reader = Reader::new(r#" "Hello all!" "Infinity" "-Infinity" "0" "-0" "#.bytes());
let nan: f32 = reader.read().unwrap();
let inf: f32 = reader.read().unwrap();
let minf: f32 = reader.read().unwrap();
let zero: f32 = reader.read().unwrap();
let mzero: f32 = reader.read().unwrap();
assert!(nan.is_nan());
assert_eq!(inf, f32::INFINITY);
assert_eq!(minf, f32::NEG_INFINITY);
assert!(zero==0.0 && !zero.is_sign_negative());
assert!(mzero==0.0 && mzero.is_sign_negative());
Structs§
Enums§
- Type to store any JSON node.
Traits§
- Trait that can be automatically derived for structs and enums. When it’s derived, a Debug implementation is also added, so the object can be printed with
println!
. - Implementing this trait makes possible for any type (except unions) to be JSON deserializable. The common technique to implement this trait is automatically through
#[derive(TryFromJson)]
. Every type that implementsTryFromJson
must also implement ValidateJson. And every deserializable field must implementDefault
. - During deserialization process, you may want to complain on invalid fields combination in struct. Every type that implements TryFromJson must also implement
ValidateJson
. This trait introduces functionvalidate_json()
.try_from_json()
calls this function right after it converted JSON string to target type, and deserialization will stop ifvalidate_json()
returnsErr
. - Trait that can be automatically derived for structs and enums.
Functions§
- Adds slashes before
"
and\
characters, converts\t
,\r
,\n
,\b
,\f
characters as needed, and encodes characters with codes less than space (32) with\u00XX
. If input string doesn’t contain something that JSON standard wants us to escape, it just returns the input string without memory allocation. - Like escape, but for
&[u8]
.
Derive Macros§
- To generate DebugToJson implementation for any struct or enum, where all members also implement DebugToJson use
#[derive(DebugToJson)]
. - To generate TryFromJson implementation for any struct or enum, where all members also implement TryFromJson use
#[derive(TryFromJson)]
. - To generate ValidateJson implementation that always passes the validation use
#[derive(ValidateJson)]
. - To generate WriteToJson implementation for any struct or enum, where all members also implement WriteToJson use
#[derive(WriteToJson)]
.