JsonReader

Struct JsonReader 

Source
pub struct JsonReader<'a, B: AsMut<[u8]>, R: BlockingRead> { /* private fields */ }
Expand description

A JsonReader wraps a sequence of bytes, aggregating them into a sequence of JSON tokens. It is in essentially a tokenizer, adding some rudimentary convenience for JSON’s grammar.

It does not try to be a full-blown JSON parser. The reason is that if an application consumes an actual JSON document, it assumes structure beyond the document being a valid JSON document (‘name is a mandatory string, age is a u32, but it is ok if it is null or not present in the first place’). JsonReader makes it easy for application code to consume data based on such assumptions - and while it does, application code checks the document’s conformity to the JSON grammar automatically.

A JsonReader wraps and consumes a BlockingRead which is basically a same abstraction as a std::io::Read but without enforcing the dependency on std. For the majority of users who don’t care about that, there is a blanket implementation of BlockingRead for std::io::Read, letting you ignore distinction between the two.

The JsonReader holds a mutable reference to the reader rather than taking ownership of it. That means it needs to have a lifetime parameter, allowing the compiler to ensure that the reader lives at least as long as the wrapping JsonReader.

The JsonReader also holds a fixed read buffer which it uses to assemble tokens. JsonReader can either work with a buffer passed to it on construction, or it can allocate the buffer as a convenience, and it does not do any memory allocation on the heap beyond that.

The buffer is fixed in length, and if some token (e.g. a string value) does not fit into the buffer, that causes a failure. While this may look like an inconvenient restriction, it is actually an important security safeguard: JSON documents often come from external sources and have limited trustworthiness at best. Without an upper bound on token size, a maliciously or negligently created document could contain a string literal with a size of a gigabyte, working as a denial-of-service attack. JSON parsers that work on materialized documents often address this by placing a restriction on the maximum size of the whole document.

The following code snippet shows a small working example of reading a JSON document with a single object:

use json_streaming::blocking::*;
use json_streaming::shared::*;

fn read_something(r: &mut impl std::io::Read) -> JsonParseResult<(), std::io::Error> {
    let mut json_reader = JsonReader::new(1024, r);

    json_reader.expect_start_object()?;
    loop {
        match json_reader.expect_key()? {
            Some("a") => println!("a: {}", json_reader.expect_string()?),
            Some("b") => println!("b: {}", json_reader.expect_string()?),
            Some(_other) => {
                return Err(JsonParseError::Parse("unexpected key parsing 'person'", json_reader.location()));
            },
            None => break,
        }
    }
    Ok(())
}

Implementations§

Source§

impl<'a, R: BlockingRead> JsonReader<'a, Vec<u8>, R>

Source

pub fn new(buf_size: usize, reader: &'a mut R) -> Self

Create a JsonReader, allocating a read buffer of given size on the heap.

Source

pub fn new_with_lenient_comma_handling( buf_size: usize, reader: &'a mut R, ) -> Self

Create a JsonReader without requiring commas between objects. This is intended for reading [https://jsonlines.org] documents - see the jsonlines.rs example for details.

Source§

impl<'a, B: AsMut<[u8]>, R: BlockingRead> JsonReader<'a, B, R>

Source

pub fn new_with_provided_buffer( buf: B, reader: &'a mut R, lenient_comma_handling: bool, ) -> Self

Create a JsonReader that uses an externally provided buffer as its read buffer. The main reason to do this is to avoid heap allocation in a no-std environment.

Source

pub fn next(&mut self) -> JsonParseResult<JsonReadToken<'_>, R::Error>

Return the next JSON token. This is the work horse of JsonReader and the foundation for other convenience abstraction.

The function does only limited checks of JSON grammar and basically returns whatever tokens it finds.

Source

pub fn expect_key(&mut self) -> JsonParseResult<Option<&str>, R::Error>

This is the function for the loop to read the members of a JSON object: It returns either a JSON key or None if it encounters the } that ends the object. All other tokens are invalid and cause the function to fail.

Source

pub fn expect_raw_number(&mut self) -> JsonParseResult<JsonNumber<'_>, R::Error>

Returns a JSON number as a JsonNumber, and fails if the next token is anything other than a number. That includes the case that the next token is null - if the number is optional and null a valid value, use JsonReader::expect_opt_raw_number instead.

Source

pub fn expect_raw_number_or_end_array( &mut self, ) -> JsonParseResult<Option<JsonNumber<'_>>, R::Error>

Same as JsonReader::expect_raw_number, except that it returns Ok(None) if it reaches the end of an array instead

Source

pub fn expect_opt_raw_number( &mut self, ) -> JsonParseResult<Option<JsonNumber<'_>>, R::Error>

Returns a JsonNumber if the next token is a JSON number, or None if the next token is null. All other tokens cause the function to fail.

Source

pub fn expect_opt_raw_number_or_end_array( &mut self, ) -> JsonParseResult<Option<Option<JsonNumber<'_>>>, R::Error>

Same as JsonReader::expect_opt_raw_number, except that it returns Ok(None) if it reaches the end of an array instead

Source

pub fn expect_number<T: FromStr>(&mut self) -> JsonParseResult<T, R::Error>

Returns a number parsed to an application-provided type, failing if the next token is not a JSON number or the number is not parseable to the provided type (e.g. trying to get retrieve a floating point number as a u32).

The expected numeric type can be provided explicitly, like this:

let n = json_reader.expect_number::<u32>()?;

or inferred by the compiler:

let n:u32 = json_reader.expect_number()?;
Source

pub fn expect_number_or_end_array<T: FromStr>( &mut self, ) -> JsonParseResult<Option<T>, R::Error>

Same as JsonReader::expect_number, except that it returns Ok(None) if it reaches the end of an array instead

Source

pub fn expect_opt_number<T: FromStr>( &mut self, ) -> JsonParseResult<Option<T>, R::Error>

The same as JsonReader::expect_number, but accepting a null literal which it returns as None.

Source

pub fn expect_opt_number_or_end_array<T: FromStr>( &mut self, ) -> JsonParseResult<Option<Option<T>>, R::Error>

Same as JsonReader::expect_opt_number, except that it returns Ok(None) if it reaches the end of an array instead

Source

pub fn expect_string(&mut self) -> JsonParseResult<&str, R::Error>

If the next token is a string literal, return that, and fail for any other token.

Source

pub fn expect_string_or_end_array( &mut self, ) -> JsonParseResult<Option<&str>, R::Error>

Same as JsonReader::expect_string, except that it returns Ok(None) if it reaches the end of an array instead

Source

pub fn expect_opt_string(&mut self) -> JsonParseResult<Option<&str>, R::Error>

The same as JsonReader::expect_string, but accepting a null literal which is returned as None.

Source

pub fn expect_opt_string_or_end_array( &mut self, ) -> JsonParseResult<Option<Option<&str>>, R::Error>

Same as JsonReader::expect_opt_string, except that it returns Ok(None) if it reaches the end of an array instead

Source

pub fn expect_bool(&mut self) -> JsonParseResult<bool, R::Error>

true and false literals are returned as a boolean token, all other tokens cause the function to fail.

Source

pub fn expect_bool_or_end_array( &mut self, ) -> JsonParseResult<Option<bool>, R::Error>

Same as JsonReader::expect_bool, except that it returns Ok(None) if it reaches the end of an array instead

Source

pub fn expect_opt_bool(&mut self) -> JsonParseResult<Option<bool>, R::Error>

The same as JsonReader::expect_bool, but accepting a null literal which is returned as None.

Source

pub fn expect_opt_bool_or_end_array( &mut self, ) -> JsonParseResult<Option<Option<bool>>, R::Error>

Same as JsonReader::expect_opt_bool, except that it returns Ok(None) if it reaches the end of an array instead

Source

pub fn expect_start_object(&mut self) -> JsonParseResult<(), R::Error>

Fails for any token except the { that starts an object.

Source

pub fn expect_start_object_or_end_array( &mut self, ) -> JsonParseResult<Option<()>, R::Error>

Same as [JsonReader::start_object], except that it returns Ok(None) if it reaches the end of an array instead

Source

pub fn expect_opt_start_object( &mut self, ) -> JsonParseResult<Option<()>, R::Error>

The same as JsonReader::expect_start_object, but accepting a null literal which is returned as None.

Source

pub fn expect_opt_start_object_or_end_array( &mut self, ) -> JsonParseResult<Option<Option<()>>, R::Error>

Same as JsonReader::expect_opt_start_object, except that it returns Ok(None) if it reaches the end of an array instead

Source

pub fn expect_end_object(&mut self) -> JsonParseResult<(), R::Error>

Fails for any token except the } that ends an object.

Source

pub fn expect_start_array(&mut self) -> JsonParseResult<(), R::Error>

Fails for any token except the [ that starts an array.

Source

pub fn expect_start_array_or_end_array( &mut self, ) -> JsonParseResult<Option<()>, R::Error>

Same as JsonReader::expect_start_array, except that it returns Ok(None) if it reaches the end of an array instead

Source

pub fn expect_opt_start_array( &mut self, ) -> JsonParseResult<Option<()>, R::Error>

The same as JsonReader::expect_start_array, but accepting a null literal which is returned as None.

Source

pub fn expect_opt_start_array_or_end_array( &mut self, ) -> JsonParseResult<Option<Option<()>>, R::Error>

Same as [JsonReader::opt_start_array], except that it returns Ok(None) if it reaches the end of an array instead

Source

pub fn expect_end_array(&mut self) -> JsonParseResult<(), R::Error>

Fails for any token except the ] that ends an array.

Source

pub fn expect_end_of_stream(&mut self) -> JsonParseResult<(), R::Error>

Fails if the stream contains any tokens - this is for checking that the entire JSON input was consumed

Source

pub fn skip_to_end_of_current_scope(&mut self) -> JsonParseResult<(), R::Error>

This function assumes that it is called inside an object or array, and silently consumes all tokens until and including the closing } or ].

This function is useful for gracefully ignoring array elements with an unsupported type. See the skipping.rs example for details.

Source

pub fn skip_value(&mut self) -> JsonParseResult<(), R::Error>

This function skips the value starting with the next token. This can be a single-token value, but it can also be an object or array of unknown structure and nesting depth, in which case this function silently consumes tokens until it reaches the matching closing } or ].

This function is useful for gracefully ignoring object members with an unknown key - see the skipping.rs example for details.

Source

pub fn parse_err<T>(&self, msg: &'static str) -> JsonParseResult<T, R::Error>

convenience function for creating a parse error with the current location

Source

pub fn location(&self) -> Location

Returns the current parse location in the underlying reader - offset, row and column.

Auto Trait Implementations§

§

impl<'a, B, R> Freeze for JsonReader<'a, B, R>
where B: Freeze,

§

impl<'a, B, R> RefUnwindSafe for JsonReader<'a, B, R>

§

impl<'a, B, R> Send for JsonReader<'a, B, R>
where B: Send, R: Send, <R as BlockingRead>::Error: Send,

§

impl<'a, B, R> Sync for JsonReader<'a, B, R>
where B: Sync, R: Sync, <R as BlockingRead>::Error: Sync,

§

impl<'a, B, R> Unpin for JsonReader<'a, B, R>
where B: Unpin, <R as BlockingRead>::Error: Unpin,

§

impl<'a, B, R> !UnwindSafe for JsonReader<'a, B, R>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.