Struct nop_json::Reader[][src]

pub struct Reader<T> where
    T: Iterator<Item = u8>, 
{ /* fields omitted */ }

Implementations

Construct new reader object, that can read values from a JSON stream, passing an object that implements Iterator<Item=u8>. This allows to use &str as data source like this:

let source = "\"Data\"";
let mut reader = Reader::new(source.bytes());

To use &[u8] do this:

let source: &[u8] = b"\"Data\"";
let mut reader = Reader::new(source.iter().map(|i| *i));

To use std::io::Read as source, you can convert it to Iterator<Item=u8> like this:

use std::io::Read;
use nop_json::Reader;
let source = std::io::stdin();
let source = source.lock(); // this implements std::io::Read
let mut reader = Reader::new(source.bytes().map(|b| b.unwrap()));

Though, this will panic on i/o error. Another technique is to use read_iter crate.

use read_iter::ReadIter;
use nop_json::Reader;
let mut source = ReadIter::new(std::io::stdin());
let mut reader = Reader::new(&mut source);
// ...
source.take_last_error().unwrap();

To read from file:

use std::fs::File;
use read_iter::ReadIter;
use nop_json::Reader;
let mut source = ReadIter::new(File::open("/tmp/test.json").unwrap());
let mut reader = Reader::new(&mut source);
// ...
source.take_last_error().unwrap();

Destroy this reader, unwrapping the underlying iterator that was passed to constructor when this object created.

Read one JSON value from the stream.

The value will be converted to target variable type with TryFromJson trait. The conversion is inspired by Javascript values conversion. For example, a JSON string that represents a number (like “123.4e5”) can be read to a numeric variable.

This method is intended for use in cases when you want to implement TryFromJson manually. Use it when you read an object with read_object() or read_object_use_buffer(). It works exactly like read(), but uses provided static string in error message. This string must be the name of the object property that you are reading.

This method is intended for use in cases when you want to implement TryFromJson manually. Use it when you read an array with read_array(). It works exactly like read(), but if error occures, the error message will contain index number in array. The index number is stored internally, and is incremented each time you call read_index() (read_array() resets it).

Creates std::io::Error from given string. The error message will be prefixed with current path in objects/arrays tree. This path is built by read_prop() and read_index().

Like format_error(), but receives std::fmt::Arguments object. Create it with format_args!().

Reads a JSON string (numbers, booleans and null will be converted to strings) to internal buffer, which is 128 bytes long. And return a reference to the read bytes. Long strings will be truncated.

This function allows us to exploit standard JSON containers to pass binary data (BLOBs, binary large objects, or Vec<u8>).

Accodring to JSON standard only valid unicode strings are valid JSON values. But the standard doesn’t specify what kind of unicode it must be: utf-8, utf-16, or other. What is invalid utf-8 can be valid utf-16, and what is invalid utf-16 can be valid something else. If we pack an invalid utf-8 sequence to a JSON container and hand it to some other application, that application will encounter errors when it will try to convert it to a string, and it will say that the JSON was invalid. But that application can not convert the bytes to string, and use the bytes themselves.

The wisdom is how to pack bytes that way. There’s trouble here only with bytes in range 80 - FF. Here is how we can encode our binary object:

  • 00 - 1F - we can encode with the \u00xx encoding - this is the only option.
  • 20 - 7F except " and \ - we can leave intact - they are valid utf-8 JSON, or optionally we can encode them with \u00xx.
  • " and \ - escape with a slash.
  • 80 - FF - leave them as they are. They make our string invalid utf-8, but we cannot encode them with \u00xx. Because \u0080 will expand to 2-byte utf-8 character on JSON-decoding.

Decoding example:

use nop_json::Reader;

let mut reader = Reader::new(b" \"\x80\x81\" ".iter().map(|i| *i));

let data = reader.read_blob().unwrap();
assert_eq!(data, b"\x80\x81");

Encoding (and decoding back) example:

use nop_json::{escape_bytes, Reader};
use std::io::Write;

let data = b"\x80\x81";
let mut json_container = Vec::with_capacity(100);
json_container.push(b'"');
json_container.write_all(escape_bytes(data).as_ref()).unwrap();
json_container.push(b'"');
assert_eq!(json_container, vec![b'"', b'\x80', b'\x81', b'"']);

let mut reader = Reader::new(json_container.iter().map(|i| *i));
let data_back = reader.read_blob().unwrap();
assert_eq!(data_back, data);

Like read_blob(), but pipes data to the provided writer.

This method is intended for use in cases when you want to implement TryFromJson manually. This method reads a JSON object from stream.

First it reads starting { char from the stream. Then it reads a property name. Then for each property name read, it calls given callback function, assuming that from this function you will read the property value using read_prop(). Reading the value with read() will also work, but in case of error, the error message will not contain path to the property where error occured.

Example:


let mut reader = Reader::new(r#" {"x": 10, "y": "the y"} "#.bytes());

let mut x: Option<i32> = None;
let mut y = String::new();

reader.read_object
(	|reader, prop|
	{	match prop.as_ref()
		{	"x" => x = reader.read_prop("x")?,
			"y" => y = reader.read_prop("y")?,
			_ => return Err(reader.format_error_fmt(format_args!("Invalid property: {}", prop)))
		}
		Ok(())
	}
)?;

assert_eq!(x, Some(10));
assert_eq!(y, "the y".to_string());

This method is intended for use in cases when you want to implement TryFromJson manually. This method reads a JSON object from stream.

First it reads starting { char from the stream. Then it reads a property name, and stores it in internal buffer. You can get it with get_key(). The buffer is 128 bytes long, so if the property name is longer, it will be truncated. To avoid this limitation, use read_object(). Then for each property name read, it calls given callback function, assuming that from this function you will read the property value using read_prop(). Reading the value with read() will also work, but in case of error, the error message will not contain path to the property where error occured.

Example:


let mut reader = Reader::new(r#" {"x": 10, "y": "the y"} "#.bytes());

let mut x: Option<i32> = None;
let mut y = String::new();

reader.read_object_use_buffer
(	|reader|
	{	match reader.get_key()
		{	b"x" => x = reader.read_prop("x")?,
			b"y" => y = reader.read_prop("y")?,
			_ => return Err(reader.format_error_fmt(format_args!("Invalid property: {}", String::from_utf8_lossy(reader.get_key()))))
		}
		Ok(())
	}
)?;

assert_eq!(x, Some(10));
assert_eq!(y, "the y".to_string());

This method is intended for use in cases when you want to implement TryFromJson manually. This method reads a JSON array from stream.

First it reads starting [ char from the stream. Then it calls given callback function as many times as needed to read each value till terminating ]. The callback function is assumed to call read_index() to read next array element.

Example:


let mut reader = Reader::new(r#" ["One", "Two", "Three"] "#.bytes());

let mut value: Vec<String> = Vec::new();

reader.read_array
(	|reader|
	{	value.push(reader.read_index()?);
		Ok(())
	}
)?;

assert_eq!(value, vec!["One".to_string(), "Two".to_string(), "Three".to_string()]);

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Performs the conversion.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.