Trait struson::reader::JsonReader
source · pub trait JsonReader {
Show 25 methods
// Required methods
fn peek(&mut self) -> Result<ValueType, ReaderError>;
fn begin_object(&mut self) -> Result<(), ReaderError>;
fn end_object(&mut self) -> Result<(), ReaderError>;
fn begin_array(&mut self) -> Result<(), ReaderError>;
fn end_array(&mut self) -> Result<(), ReaderError>;
fn has_next(&mut self) -> Result<bool, ReaderError>;
fn next_name(&mut self) -> Result<&str, ReaderError>;
fn next_name_owned(&mut self) -> Result<String, ReaderError>;
fn next_str(&mut self) -> Result<&str, ReaderError>;
fn next_string(&mut self) -> Result<String, ReaderError>;
fn next_string_reader(&mut self) -> Result<impl Read + '_, ReaderError>;
fn next_number_as_str(&mut self) -> Result<&str, ReaderError>;
fn next_number_as_string(&mut self) -> Result<String, ReaderError>;
fn next_bool(&mut self) -> Result<bool, ReaderError>;
fn next_null(&mut self) -> Result<(), ReaderError>;
fn deserialize_next<'de, D: Deserialize<'de>>(
&mut self
) -> Result<D, DeserializerError>;
fn skip_name(&mut self) -> Result<(), ReaderError>;
fn skip_value(&mut self) -> Result<(), ReaderError>;
fn skip_to_top_level(&mut self) -> Result<(), ReaderError>;
fn transfer_to<W: JsonWriter>(
&mut self,
json_writer: &mut W
) -> Result<(), TransferError>;
fn consume_trailing_whitespace(self) -> Result<(), ReaderError>;
fn current_position(&self, include_path: bool) -> JsonReaderPosition;
// Provided methods
fn next_number<T: FromStr>(
&mut self
) -> Result<Result<T, T::Err>, ReaderError> { ... }
fn seek_to(&mut self, rel_json_path: &JsonPath) -> Result<(), ReaderError> { ... }
fn seek_back(&mut self, rel_json_path: &JsonPath) -> Result<(), ReaderError> { ... }
}
Expand description
A trait for JSON readers
The methods of this reader can be divided into the following categories:
- Peeking values, without consuming them
- Reading values
begin_array
,end_array
: Starting and ending a JSON arraybegin_object
,end_object
: Starting and ending a JSON objectnext_name
,next_name_owned
: Reading the name of a JSON object membernext_str
,next_string
,next_string_reader
: Reading a JSON string valuenext_number
,next_number_as_str
,next_number_as_string
: Reading a JSON number valuenext_bool
: Reading a JSON boolean valuenext_null
: Reading a JSON null valuedeserialize_next
: Deserializes a SerdeDeserialize
from the next value (optional feature)
- Skipping values
skip_name
: Skipping the name of a JSON object memberskip_value
: Skipping a valueseek_to
: Skipping values until a specified location is reachedseek_back
: Opposite ofseek_to
skip_to_top_level
: Skipping the remaining elements of all enclosing JSON arrays and objects
- Other:
transfer_to
: Reading a JSON value and writing it to a given JSON writerconsume_trailing_whitespace
: Consuming trailing whitespace at the end of the JSON document
JSON documents have at least one top-level value which can be either a JSON array, object,
string, number, boolean or null value. For JSON arrays and objects the opening brackets
must be consumed with the corresponding begin_
method (for example begin_array
) and the
closing bracket with the corresponding end_
method (for example end_array
). JSON objects
consist of members which are name-value pairs. The name of a member can be read with
next_name
and the value with any of the value reading methods such as next_bool
.
It is not necessary to consume the complete JSON document, for example a user of this reader
can simply drop the reader once the relevant information was extracted, ignoring the remainder
of the JSON data. However, in that case no validation will be performed that the remainder
has actually valid JSON syntax. To ensure that, skip_to_top_level
can be used to skip (and validate) the remainder of the current top-level JSON array or object.
Important: Even after the top-level has been fully consumed this reader does not
automatically consume the remainder of the JSON document (which is expected to consist
of optional whitespace only). To verify that there is no trailing data it is necessary
to explicitly call consume_trailing_whitespace
.
§Examples
// In this example JSON data comes from a string;
// normally it would come from a file or a network connection
let json = r#"{"a": [1, 2, true]}"#;
let mut json_reader = JsonStreamReader::new(json.as_bytes());
json_reader.begin_object()?;
assert_eq!(json_reader.next_name()?, "a");
json_reader.begin_array()?;
assert_eq!(json_reader.next_number::<u32>()??, 1);
json_reader.skip_value()?;
assert_eq!(json_reader.next_bool()?, true);
json_reader.end_array()?;
json_reader.end_object()?;
// Ensures that there is no trailing data
json_reader.consume_trailing_whitespace()?;
§Error handling
The methods of this reader return a Result::Err
when an error occurs while reading
the JSON document. The error can for example be caused by an IO error from the underlying
reader, a JSON syntax error or an unexpected structure of the JSON document.
See ReaderError
for more details.
When encountering ReaderError::SyntaxError
and ReaderError::IoError
processing the
JSON document must be aborted. Trying to call any reader methods afterwards can lead
to unspecified behavior, such as errors, panics or incorrect data. However, no undefined
behavior occurs.
When encountering ReaderError::UnexpectedValueType
or ReaderError::UnexpectedStructure
depending on the use case it might be possible to continue processing the JSON document
(except for seek_to
where it might not be obvious how many elements have already been
skipped). However, these errors can usually be avoided by using either peek
or has_next
before trying to consume a value whose type is not known in advance, or for which it
is not known whether it is present in the JSON document.
In general it is recommended to handle errors with the ?
operator of Rust, for example
json_reader.next_bool()?
and to abort processing the JSON document when an error occurs.
§Panics
Methods of this reader panic when used in an incorrect way. The documentation of the methods
describes in detail the situations when that will happen. In general all these cases are
related to incorrect usage by the user (such as trying to call end_object
when currently
reading a JSON array) and are unrelated to the JSON data which is processed.
Required Methods§
sourcefn peek(&mut self) -> Result<ValueType, ReaderError>
fn peek(&mut self) -> Result<ValueType, ReaderError>
Peeks at the type of the next value, without consuming it
Peeking at the type of a value can be useful when the exact structure of a JSON document is not known in advance, or when a value could be of more than one type. The value can then be consumed with one of the other methods.
This method does not guarantee that the peeked value is complete or valid; consuming it (with a separate method call) can return an error when malformed JSON data is detected.
§Examples
match json_reader.peek()? {
ValueType::Boolean => println!("A boolean: {}", json_reader.next_bool()?),
ValueType::String => println!("A string: {}", json_reader.next_str()?),
_ => panic!("Unexpected type"),
}
§Errors
(besides ReaderError::SyntaxError
and ReaderError::IoError
)
If there is no next value a ReaderError::UnexpectedStructure
is returned. The method
has_next
can be used to check if there is a next value.
§Panics
Panics when called on a JSON reader which currently expects a member name, or
when called after the top-level value has already been consumed and multiple top-level
values are not enabled in the ReaderSettings
. Both cases indicate incorrect
usage by the user and are unrelated to the JSON data.
sourcefn begin_object(&mut self) -> Result<(), ReaderError>
fn begin_object(&mut self) -> Result<(), ReaderError>
Begins consuming a JSON object
The method has_next
can be used to check if there is a next object member.
To consume a member first call next_name
or next_name_owned
and afterwards one of the value reading methods such as next_number
.
At the end call end_object
to consume the closing bracket of the JSON object.
§Examples
let mut json_reader = JsonStreamReader::new(r#"{"a": 1, "b": 2}"#.as_bytes());
json_reader.begin_object()?;
// Prints "a: 1", "b: 2"
while json_reader.has_next()? {
let name = json_reader.next_name_owned()?;
let value: u32 = json_reader.next_number()??;
println!("{name}: {value}");
}
json_reader.end_object()?;
§Errors
(besides ReaderError::SyntaxError
and ReaderError::IoError
)
If there is no next value a ReaderError::UnexpectedStructure
is returned. The has_next
method can be used to check if there is a next value.
If the next value is not a JSON object but is a value of a different type
a ReaderError::UnexpectedValueType
is returned. The peek
method can be used to
check the type if it is not known in advance.
§Panics
Panics when called on a JSON reader which currently expects a member name, or
when called after the top-level value has already been consumed and multiple top-level
values are not enabled in the ReaderSettings
. Both cases indicate incorrect
usage by the user and are unrelated to the JSON data.
sourcefn end_object(&mut self) -> Result<(), ReaderError>
fn end_object(&mut self) -> Result<(), ReaderError>
Consumes the closing bracket }
of the current JSON object
This method is used to end a JSON object started by begin_object
.
§Errors
(besides ReaderError::SyntaxError
and ReaderError::IoError
)
If there are remaining members in the object a ReaderError::UnexpectedStructure
is returned.
skip_name
and skip_value
can be used to skip these
remaining members in case they should be ignored:
while json_reader.has_next()? {
// Skip member name
json_reader.skip_name()?;
// Skip member value
json_reader.skip_value()?;
}
json_reader.end_object()?;
§Panics
Panics when called on a JSON reader which is currently not inside a JSON object, or when the value of a member is currently expected. Both cases indicate incorrect usage by the user and are unrelated to the JSON data.
sourcefn begin_array(&mut self) -> Result<(), ReaderError>
fn begin_array(&mut self) -> Result<(), ReaderError>
Begins consuming a JSON array
The method has_next
can be used to check if there is a next array item. To consume an item one of
the regular value reading methods such as next_number
can be used. At the end call
end_array
to consume the closing bracket of the JSON array.
Note that JSON arrays can contain values of different types, so for example the
following is valid JSON: [1, true, "a"]
§Examples
let mut json_reader = JsonStreamReader::new("[1, 2, 3]".as_bytes());
json_reader.begin_array()?;
// Prints: "Number: 1", "Number: 2", "Number: 3"
while json_reader.has_next()? {
let number: u32 = json_reader.next_number()??;
println!("Number: {number}");
}
json_reader.end_array()?;
§Errors
(besides ReaderError::SyntaxError
and ReaderError::IoError
)
If there is no next value a ReaderError::UnexpectedStructure
is returned. The has_next
method can be used to check if there is a next value.
If the next value is not a JSON array but is a value of a different type
a ReaderError::UnexpectedValueType
is returned. The peek
method can be used to
check the type if it is not known in advance.
§Panics
Panics when called on a JSON reader which currently expects a member name, or
when called after the top-level value has already been consumed and multiple top-level
values are not enabled in the ReaderSettings
. Both cases indicate incorrect
usage by the user and are unrelated to the JSON data.
sourcefn end_array(&mut self) -> Result<(), ReaderError>
fn end_array(&mut self) -> Result<(), ReaderError>
Consumes the closing bracket ]
of the current JSON array
This method is used to end a JSON array started by begin_array
.
§Errors
(besides ReaderError::SyntaxError
and ReaderError::IoError
)
If there are remaining items in the array a ReaderError::UnexpectedStructure
is returned.
skip_value
can be used to skip these remaining items in case they should be ignored:
while json_reader.has_next()? {
json_reader.skip_value()?;
}
json_reader.end_array()?;
§Panics
Panics when called on a JSON reader which is currently not inside a JSON array. This indicates incorrect usage by the user and is unrelated to the JSON data.
sourcefn has_next(&mut self) -> Result<bool, ReaderError>
fn has_next(&mut self) -> Result<bool, ReaderError>
Checks if there is a next element in the current JSON array or object, without consuming it
Returns true
if there is a next element, false
otherwise. When multiple top-level
values are allowed by the ReaderSettings
this method can also be used to check if
there are more top-level values.
This method can be useful as condition of a while
loop when processing a JSON array or object
of unknown size.
§Examples
let mut json_reader = JsonStreamReader::new("[1]".as_bytes());
json_reader.begin_array()?;
// Array has a next item
assert!(json_reader.has_next()?);
json_reader.skip_value()?;
// Array does not have a next item anymore
assert_eq!(json_reader.has_next()?, false);
§Panics
Panics when called on a JSON reader which currently expects a member name, or
when called after the top-level value has already been consumed and multiple top-level
values are not enabled in the ReaderSettings
. Both cases indicate incorrect
usage by the user and are unrelated to the JSON data.
Additionally this method also panics when called on a JSON reader which has not consumed any top-level value yet. An empty JSON document is not valid so there should be no need to check for a next element since there must always be one.
sourcefn next_name(&mut self) -> Result<&str, ReaderError>
fn next_name(&mut self) -> Result<&str, ReaderError>
Consumes and returns the name of the next JSON object member as str
The name is returned as borrowed str
. While that value is in scope, the Rust
compiler might not permit using the JSON reader in any other way.
If an owned String
is needed, prefer next_name_owned
,
that will most likely be more efficient than using this method to obtain a str
and then converting that to an owned String
.
Afterwards one of the value reading methods such as next_number
can be
used to read the corresponding member value.
Important: This method does not detect duplicate member names, such as
in {"a": 1, "a": 2}
. Programs processing JSON data from an untrusted source
must implement this detection themselves to protect against exploits relying
on different handling of duplicate names by different JSON parsing libraries.
§Examples
let mut json_reader = JsonStreamReader::new(r#"{"a": 1}"#.as_bytes());
json_reader.begin_object()?;
assert_eq!(json_reader.next_name()?, "a");
§Errors
(besides ReaderError::SyntaxError
and ReaderError::IoError
)
If there is no next object member a ReaderError::UnexpectedStructure
is returned.
has_next
can be used to check if there are further members in the current JSON object.
§Panics
Panics when called on a JSON reader which currently does not expect a member name. This indicates incorrect usage by the user and is unrelated to the JSON data.
sourcefn next_name_owned(&mut self) -> Result<String, ReaderError>
fn next_name_owned(&mut self) -> Result<String, ReaderError>
Consumes and returns the name of the next JSON object member as String
The name is returned as owned String
. If a borrowed str
suffices for
your use case, prefer next_name
, that will most likely
be more efficient.
See the documentation of next_name
for a detailed
description of the behavior of reading a member name.
sourcefn next_str(&mut self) -> Result<&str, ReaderError>
fn next_str(&mut self) -> Result<&str, ReaderError>
Consumes and returns a JSON string value as str
This method is only intended to consume string values, it cannot be used to consume
JSON object member names. The method next_name
has to be used for that.
The string value is returned as borrowed str
. While that value is in scope, the Rust
compiler might not permit using the JSON reader in any other way.
If an owned String
is needed, prefer next_string
,
that will most likely be more efficient than using this method to obtain a str
and then converting that to an owned String
.
To avoid reading the complete string value into memory, the method next_string_reader
can be used to obtain a reader which allows lazily reading the value. Especially for
large string values this can be useful.
§Examples
let mut json_reader = JsonStreamReader::new(r#""text with \"quotes\"""#.as_bytes());
assert_eq!(json_reader.next_str()?, "text with \"quotes\"");
§Errors
(besides ReaderError::SyntaxError
and ReaderError::IoError
)
If there is no next value a ReaderError::UnexpectedStructure
is returned. The has_next
method can be used to check if there is a next value.
If the next value is not a JSON string value but is a value of a different type
a ReaderError::UnexpectedValueType
is returned. The peek
method can be used to
check the type if it is not known in advance.
§Panics
Panics when called on a JSON reader which currently expects a member name, or
when called after the top-level value has already been consumed and multiple top-level
values are not enabled in the ReaderSettings
. Both cases indicate incorrect
usage by the user and are unrelated to the JSON data.
sourcefn next_string(&mut self) -> Result<String, ReaderError>
fn next_string(&mut self) -> Result<String, ReaderError>
Consumes and returns a JSON string value as String
The string value is returned as owned String
. If a borrowed str
suffices
for your use case, prefer next_str
, that will most likely
be more efficient.
See the documentation of next_str
for a detailed
description of the behavior of reading a string value.
sourcefn next_string_reader(&mut self) -> Result<impl Read + '_, ReaderError>
fn next_string_reader(&mut self) -> Result<impl Read + '_, ReaderError>
Provides a reader for lazily reading a JSON string value
This method is mainly designed to process large string values in a memory efficient
way. If that is not a concern the method next_str
should be used instead.
This method is only intended to consume string values, it cannot be used to consume
JSON object member names. The method next_name
has to be used for that.
Escape sequences will be automatically converted to the corresponding characters.
Important: The data of the string value reader must be fully consumed, that means
read
has to be called with a non-empty buffer until it returns Ok(0)
. Otherwise the
string value reader will still be considered ‘active’ and all methods of this JSON reader
will panic. Note that after finishing reading from the string value reader, it might be
necessary to explicitly drop(...)
it for the Rust compiler to allow using the original
JSON reader again.
§Examples
let mut json_reader = JsonStreamReader::new(r#"["hello"]"#.as_bytes());
json_reader.begin_array()?;
let mut string_reader = json_reader.next_string_reader()?;
let mut buf = [0_u8; 1];
// Important: This calls read until it returns Ok(0) to properly end the string value
while string_reader.read(&mut buf)? > 0 {
println!("Read byte: {}", buf[0]);
}
// Drop the string reader to allow using the JSON reader again
drop(string_reader);
json_reader.end_array()?;
§Errors
(besides ReaderError::SyntaxError
and ReaderError::IoError
)
If there is no next value a ReaderError::UnexpectedStructure
is returned. The has_next
method can be used to check if there is a next value.
If the next value is not a JSON string value but is a value of a different type
a ReaderError::UnexpectedValueType
is returned. The peek
method can be used to
check the type if it is not known in advance.
§Reader errors
JSON syntax errors and invalid UTF-8 data which occurs while consuming the JSON string
value with the reader are reported as std::io::Error
for that reader.
The error behavior of the string reader differs from the guarantees made by Read
:
- if an error is returned there are no guarantees about if or how many data has been
consumed from the underlying data source and been stored in the provided
buf
- if an error occurs, processing should be aborted, regardless of the kind of the error; trying to use the string reader or the underlying JSON reader afterwards will lead to unspecified behavior
§Panics
Panics when called on a JSON reader which currently expects a member name, or
when called after the top-level value has already been consumed and multiple top-level
values are not enabled in the ReaderSettings
. Both cases indicate incorrect
usage by the user and are unrelated to the JSON data.
sourcefn next_number_as_str(&mut self) -> Result<&str, ReaderError>
fn next_number_as_str(&mut self) -> Result<&str, ReaderError>
Consumes and returns the string representation of a JSON number value as str
This method is mainly intended for situations where parsing the number should be deferred to a later point, or the exact format of the JSON number should be preserved. However, this method nonetheless validates that the JSON number matches the format described by the JSON specification.
The method next_number
can be used instead to parse the number directly in place.
The number value is returned as borrowed str
. While that value is in scope, the Rust
compiler might not permit using the JSON reader in any other way.
If an owned String
is needed, prefer next_number_as_string
,
that will most likely be more efficient than using this method to obtain a str
and then converting that to an owned String
.
§Examples
let mut json_reader = JsonStreamReader::new("12.0e5".as_bytes());
assert_eq!(json_reader.next_number_as_str()?, "12.0e5");
§Errors
(besides ReaderError::SyntaxError
and ReaderError::IoError
)
If there is no next value a ReaderError::UnexpectedStructure
is returned. The has_next
method can be used to check if there is a next value.
If the next value is not a JSON number value but is a value of a different type
a ReaderError::UnexpectedValueType
is returned. The peek
method can be used to
check the type if it is not known in advance.
If the number is too large or has too many decimal places a ReaderError::UnsupportedNumberValue
is returned, depending on the reader settings.
§Panics
Panics when called on a JSON reader which currently expects a member name, or
when called after the top-level value has already been consumed and multiple top-level
values are not enabled in the ReaderSettings
. Both cases indicate incorrect
usage by the user and are unrelated to the JSON data.
sourcefn next_number_as_string(&mut self) -> Result<String, ReaderError>
fn next_number_as_string(&mut self) -> Result<String, ReaderError>
Consumes and returns the string representation of a JSON number value as String
The string value is returned as owned String
. If a borrowed str
suffices
for your use case, prefer next_number_as_str
, that
will most likely be more efficient.
See the documentation of next_number_as_str
for
a detailed description of the behavior of reading a number value as string.
sourcefn next_bool(&mut self) -> Result<bool, ReaderError>
fn next_bool(&mut self) -> Result<bool, ReaderError>
Consumes and returns a JSON boolean value
§Examples
let mut json_reader = JsonStreamReader::new("true".as_bytes());
assert_eq!(json_reader.next_bool()?, true);
§Errors
(besides ReaderError::SyntaxError
and ReaderError::IoError
)
If there is no next value a ReaderError::UnexpectedStructure
is returned. The has_next
method can be used to check if there is a next value.
If the next value is not a JSON boolean value but is a value of a different type
a ReaderError::UnexpectedValueType
is returned. The peek
method can be used to
check the type if it is not known in advance.
§Panics
Panics when called on a JSON reader which currently expects a member name, or
when called after the top-level value has already been consumed and multiple top-level
values are not enabled in the ReaderSettings
. Both cases indicate incorrect
usage by the user and are unrelated to the JSON data.
sourcefn next_null(&mut self) -> Result<(), ReaderError>
fn next_null(&mut self) -> Result<(), ReaderError>
Consumes a JSON null value
This method does not return a value since there is nothing meaningful to return. Either the JSON value is a JSON null, or otherwise an error is returned because the value had a different type (see “Errors” section below).
§Examples
let mut json_reader = JsonStreamReader::new("null".as_bytes());
json_reader.next_null()?;
§Errors
(besides ReaderError::SyntaxError
and ReaderError::IoError
)
If there is no next value a ReaderError::UnexpectedStructure
is returned. The has_next
method can be used to check if there is a next value.
If the next value is not a JSON null value but is a value of a different type
a ReaderError::UnexpectedValueType
is returned. The peek
method can be used to
check the type if it is not known in advance.
§Panics
Panics when called on a JSON reader which currently expects a member name, or
when called after the top-level value has already been consumed and multiple top-level
values are not enabled in the ReaderSettings
. Both cases indicate incorrect
usage by the user and are unrelated to the JSON data.
sourcefn deserialize_next<'de, D: Deserialize<'de>>(
&mut self
) -> Result<D, DeserializerError>
Available on crate feature serde
only.
fn deserialize_next<'de, D: Deserialize<'de>>( &mut self ) -> Result<D, DeserializerError>
serde
only.Deserializes a Serde Deserialize
from the next value
This method is part of the optional Serde integration feature, see the
serde
module of this crate for more information.
If it is not possible to directly deserialize a value in place, instead of using
this method a JsonReaderDeserializer
can be constructed and deserialization can be performed using it later on. However,
this should only be rarely necessary.
§Examples
// In this example JSON data comes from a string;
// normally it would come from a file or a network connection
let json = r#"{"outer": {"text": "some text", "number": 5}}"#;
let mut json_reader = JsonStreamReader::new(json.as_bytes());
// Skip outer data using the regular JsonReader methods
json_reader.seek_to(&json_path!["outer"])?;
#[derive(Deserialize, PartialEq, Debug)]
struct MyStruct {
text: String,
number: u64,
}
let value: MyStruct = json_reader.deserialize_next()?;
// Skip the remainder of the JSON document
json_reader.skip_to_top_level()?;
// Ensures that there is no trailing data
json_reader.consume_trailing_whitespace()?;
assert_eq!(
value,
MyStruct { text: "some text".to_owned(), number: 5 }
);
§Security
Since JSON data can have an arbitrary structure and can contain arbitrary
data, care must be taken when processing untrusted data. See the documentation
of JsonReaderDeserializer
for
security considerations.
§Errors
Errors can occur when either this JSON reader or the Deserialize
encounters an
error. In which situations this can happen depends on the Deserialize
implementation.
§Panics
Panics when called on a JSON reader which currently expects a member name, or
when called after the top-level value has already been consumed and multiple top-level
values are not enabled in the ReaderSettings
. Both cases indicate incorrect
usage by the user and are unrelated to the JSON data.
sourcefn skip_name(&mut self) -> Result<(), ReaderError>
fn skip_name(&mut self) -> Result<(), ReaderError>
Skips the name of the next JSON object member
Afterwards one of the value reading methods such as next_number
can be
used to read the corresponding member value.
Skipping member names can be useful when the only the values of the JSON object members are relevant for the application processing the JSON document but the member names don’t matter.
Skipping member names with this method is usually more efficient than calling next_name
but discarding its result. However, skip_name
nonetheless also verifies that the skipped
name has valid syntax.
§Examples
let mut json_reader = JsonStreamReader::new(r#"{"a": 1}"#.as_bytes());
json_reader.begin_object()?;
// Skip member name "a"
json_reader.skip_name()?;
assert_eq!(json_reader.next_number_as_str()?, "1");
To skip to a specific location in the JSON document the method seek_to
can be used.
§Errors
(besides ReaderError::SyntaxError
and ReaderError::IoError
)
If there is no next object member a ReaderError::UnexpectedStructure
is returned.
has_next
can be used to check if there are further members in the current JSON object.
§Panics
Panics when called on a JSON reader which currently does not expect a member name. This indicates incorrect usage by the user and is unrelated to the JSON data.
sourcefn skip_value(&mut self) -> Result<(), ReaderError>
fn skip_value(&mut self) -> Result<(), ReaderError>
Skips the next value
This method can be used to skip top-level values, JSON array items and JSON object member
values. To skip an object member name, the method skip_name
has to be used.
Skipping a JSON array or object skips the complete value including all nested ones, if any.
Skipping values can be useful when parts of the processed JSON document are not relevant for the application processing it.
Skipping values with this method is usually more efficient than calling regular value reading
methods (such as next_str()
) but discarding their result.
However, skip_value
nonetheless also verifies that the skipped JSON data has valid syntax.
§Examples
let mut json_reader = JsonStreamReader::new(r#"{"a": [{}], "b": 1}"#.as_bytes());
json_reader.begin_object()?;
assert_eq!(json_reader.next_name()?, "a");
// Skip member value [{}]
json_reader.skip_value()?;
assert_eq!(json_reader.next_name()?, "b");
To skip to a specific location in the JSON document the method seek_to
can be used.
§Errors
(besides ReaderError::SyntaxError
and ReaderError::IoError
)
If there is no next value a ReaderError::UnexpectedStructure
is returned. The has_next
method can be used to check if there is a next value.
§Panics
Panics when called on a JSON reader which currently expects a member name (skip_name
has to be used for that), or when called after the top-level value has already been consumed
and multiple top-level values are not enabled in the ReaderSettings
. Both cases indicate
incorrect usage by the user and are unrelated to the JSON data.
sourcefn skip_to_top_level(&mut self) -> Result<(), ReaderError>
fn skip_to_top_level(&mut self) -> Result<(), ReaderError>
Skips the remaining elements of all currently enclosing JSON arrays and objects
Based on the current JSON reader position skips the remaining elements of all enclosing
JSON arrays and objects (if any) until the top-level is reached. That is, for every array
started with begin_array
and for every object started with begin_object
the remaining elements are skipped and the end of the array respectively object is consumed.
During skipping, the syntax of the skipped values is validated. Calling this method has no
effect when there is currently no enclosing JSON array or object.
This method is useful when a subsection of a JSON document has been consumed, for example
with the help of seek_to
, and afterwards either
- the syntax of the remainder of the document should be validated and trailing data should
be rejected, by calling
consume_trailing_whitespace
- or, multiple top-level values are enabled in the
ReaderSettings
and the next top-level value should be consumed
§Examples
let mut json_reader = JsonStreamReader::new(
r#"{"bar": true, "foo": ["a", "b", "c"]}"#.as_bytes()
);
json_reader.seek_to(&json_path!["foo", 2])?;
// Consume the value to which the call seeked to
assert_eq!(json_reader.next_str()?, "c");
// Skip the remainder of the document
json_reader.skip_to_top_level()?;
// And verify that there is only optional whitespace, but no trailing data
json_reader.consume_trailing_whitespace()?;
§Errors
None, besides ReaderError::SyntaxError
and ReaderError::IoError
.
sourcefn transfer_to<W: JsonWriter>(
&mut self,
json_writer: &mut W
) -> Result<(), TransferError>
fn transfer_to<W: JsonWriter>( &mut self, json_writer: &mut W ) -> Result<(), TransferError>
Consumes the next value and writes it to the given JSON writer
This method consumes the next value and calls the corresponding methods on the
JSON writer to emit the value again. Due to this, whitespace and comments, if enabled
in the ReaderSettings
, are not preserved. Instead the formatting of the output
is dependent on the configuration of the JSON writer. Similarly the Unicode characters
of member names and string values might be escaped differently. However, all these differences
don’t have an effect on the JSON value. JSON readers will consider it to be equivalent.
For JSON numbers the exact format is preserved.
This method is useful for extracting a subsection from a JSON document and / or for
embedding it into another JSON document. Extraction can be done by using for example
seek_to
to position the reader before calling this method. Embedding
can be done by already writing JSON data to the JSON writer before calling this method.
§Examples
let mut json_reader = JsonStreamReader::new(
r#"{"bar": true, "foo": [1, 2]}"#.as_bytes()
);
json_reader.seek_to(&json_path!["foo"])?;
let mut writer = Vec::<u8>::new();
let mut json_writer = JsonStreamWriter::new(&mut writer);
json_writer.begin_object()?;
json_writer.name("embedded")?;
// Extract subsection from reader and embed it in the document created by the writer
json_reader.transfer_to(&mut json_writer)?;
json_writer.end_object()?;
json_writer.finish_document()?;
let json = String::from_utf8(writer)?;
assert_eq!(json, r#"{"embedded":[1,2]}"#);
§Errors
Errors are reported as TransferError
which wraps either an error which occurred for this
JSON reader or an error which occurred for the given JSON writer.
§Reader errors
(besides ReaderError::SyntaxError
and ReaderError::IoError
)
If there is no next value a ReaderError::UnexpectedStructure
is returned. The has_next
method can be used to check if there is a next value.
§Writer errors
If writing the JSON value fails an IO error is returned.
§Panics
Panics when called on a JSON reader which currently expects a member name, or
when called after the top-level value has already been consumed and multiple top-level
values are not enabled in the ReaderSettings
.
Panics when the given JSON writer currently expects a member name, or when it has already
written a top-level value and multiple top-level values are not enabled in the
WriterSettings
.
These cases indicate incorrect usage by the user and are unrelated to the JSON data.
sourcefn consume_trailing_whitespace(self) -> Result<(), ReaderError>
fn consume_trailing_whitespace(self) -> Result<(), ReaderError>
Consumes trailing whitespace at the end of the top-level value
Additionally, if comments are allowed by the ReaderSettings
also consumes trailing comments.
If there is any trailing data a ReaderError::SyntaxError
is returned.
This method can be useful to verify that a JSON document is wellformed and does not have any unexpected data at the end. This is not checked automatically by this JSON reader.
When multiple top-level values are allowed by the ReaderSettings
but not all
top-level values are relevant they can be skipped with of loop calling has_next
and skip_value
to allow calling consume_trailing_whitespace
eventually:
// Skip all remaining top-level values
while json_reader.has_next()? {
json_reader.skip_value()?;
}
// Verify that there is only optional whitespace, but no trailing data
json_reader.consume_trailing_whitespace()?;
Important: It is expected that there is always at least one top-level value in a JSON document, so calling this method without having consumed a value yet will panic, see “Panics” section below.
§Errors
(besides ReaderError::IoError
)
If there is trailing data at the end of the top-level value a ReaderError::SyntaxError
of kind SyntaxErrorKind::TrailingData
is returned.
§Panics
Panics when called on a JSON reader which has not read any top-level yet, or when called while the top-level value has not been fully consumed yet. Both cases indicate incorrect usage by the user and are unrelated to the JSON data.
sourcefn current_position(&self, include_path: bool) -> JsonReaderPosition
fn current_position(&self, include_path: bool) -> JsonReaderPosition
Gets the current position of this JSON reader within the JSON data
The position can be used to enhance custom errors when building a parser on top
of this JSON reader. include_path
determines whether the JSON path
should be included, assuming the JSON reader implementation supports providing
this information (if it doesn’t the path will be None
regardless of include_path
value). Including the JSON path can make the position information more useful
for troubleshooting. However, if a caller frequently requests the position,
for example to have it providently in case subsequent parsing fails, then it
might improve performance to not include the path information.
Line and data position
are only specified if has_next
or peek
have just
been called, in which case their values point at the start of the next token. Otherwise
their values can be anywhere between the previous token and the next token (if any).
The position information makes no guarantee about the amount of data (e.g. number of bytes) consumed from the underlying data source. JSON reader implementations might buffer data which has not been processed yet.
§Examples
Let’s assume an array of points encoded as JSON string in the format x|y
should
be parsed:
let mut json_reader = JsonStreamReader::new(
r#"["1|2", "3|2", "8"]"#.as_bytes()
);
json_reader.begin_array()?;
while json_reader.has_next()? {
let pos = json_reader.current_position(true);
let encoded_point = json_reader.next_str()?;
if let Some((x, y)) = encoded_point.split_once('|') {
// ...
} else {
// Includes the JSON reader position for easier troubleshooting
println!("Malformed point '{encoded_point}', at {pos}");
}
}
Provided Methods§
sourcefn next_number<T: FromStr>(&mut self) -> Result<Result<T, T::Err>, ReaderError>
fn next_number<T: FromStr>(&mut self) -> Result<Result<T, T::Err>, ReaderError>
Consumes and returns a JSON number value
The result is either the parsed number or the parse error. It might be necessary to help the Rust compiler a bit by explicitly specifying the number type in case it cannot be inferred automatically.
If parsing the number should be deferred to a later point or the exact format of the
JSON number should be preserved, the method next_number_as_str
can be used.
§Examples
let mut json_reader = JsonStreamReader::new("12".as_bytes());
assert_eq!(json_reader.next_number::<u32>()??, 12);
§Errors
(besides ReaderError::SyntaxError
and ReaderError::IoError
)
If there is no next value a ReaderError::UnexpectedStructure
is returned. The has_next
method can be used to check if there is a next value.
If the next value is not a JSON number value but is a value of a different type
a ReaderError::UnexpectedValueType
is returned. The peek
method can be used to
check the type if it is not known in advance.
If the number is too large or has too many decimal places a ReaderError::UnsupportedNumberValue
is returned, depending on the reader settings.
§Panics
Panics when called on a JSON reader which currently expects a member name, or
when called after the top-level value has already been consumed and multiple top-level
values are not enabled in the ReaderSettings
. Both cases indicate incorrect
usage by the user and are unrelated to the JSON data.
sourcefn seek_to(&mut self, rel_json_path: &JsonPath) -> Result<(), ReaderError>
fn seek_to(&mut self, rel_json_path: &JsonPath) -> Result<(), ReaderError>
Seeks to the specified location in the JSON document
Seeks to the specified relative JSON path in the JSON document by skipping all previous values. The JSON reader is expected to be positioned before the first value specified in the path. Once this method returns successfully the reader will be positioned before the last element specified by the path.
For example for the JSON path json_path!["foo", 2]
it will start consuming a JSON object,
skipping members until it finds one with name “foo”. Then it starts consuming the member
value, expecting that it is a JSON array, until right before the array item with (starting
at 0) index 2. If multiple members in a JSON object have the same name (for example
{"a": 1, "a": 2}
) this method will seek to the first occurrence.
Seeking to a specific location can be useful when parts of the processed JSON document are not relevant for the application processing it.
To continue reading at the original nesting level before seek_to
had been called,
use seek_back
afterwards.
§Examples
let mut json_reader = JsonStreamReader::new(
r#"{"bar": true, "foo": ["a", "b", "c"]}"#.as_bytes()
);
json_reader.seek_to(&json_path!["foo", 2])?;
// Can now consume the value to which the call seeked to
assert_eq!(json_reader.next_str()?, "c");
§Errors
(besides ReaderError::SyntaxError
and ReaderError::IoError
)
If the structure or the value types of the JSON document do not match the structure expected
by the JSON path, either a ReaderError::UnexpectedStructure
or a ReaderError::UnexpectedValueType
is returned.
§Panics
Panics when called on a JSON reader which currently expects a member name, or
when called after the top-level value has already been consumed and multiple top-level
values are not enabled in the ReaderSettings
. Both cases indicate incorrect
usage by the user and are unrelated to the JSON data.
sourcefn seek_back(&mut self, rel_json_path: &JsonPath) -> Result<(), ReaderError>
fn seek_back(&mut self, rel_json_path: &JsonPath) -> Result<(), ReaderError>
Opposite of seek_to
This is the opposite of the seek_to
method; it goes through the path in reverse
order skipping remaining JSON array items and object members and closing arrays
and objects. Therefore once this method returns the reader is at the same nesting
level it was before seek_to
had been called and allows continuing reading
values there.
For directly getting to the top-level regardless of the current position of the
JSON reader, prefer skip_to_top_level
instead.
The correct usage looks like this:
- Call
seek_to
with path - Read one or more values
- Call
seek_back
with the same path
Using this method in a different way can lead to errors and panics. In particular it is important that for step 2:
- the value and all nested values (if any) are fully consumed; any additional JSON arrays and objects which are started must be closed again
- no enclosing JSON arrays or objects must be closed
- if the path points to the member of a JSON object, then for every additionally read member name of that object the corresponding member value must be consumed as well
§Examples
let mut json_reader = JsonStreamReader::new(
r#"[{"a": {"b": "first"}}, {"a": {"b": "second"}}]"#.as_bytes()
);
let mut values = Vec::<String>::new();
json_reader.begin_array()?;
while json_reader.has_next()? {
let path = json_path!["a", "b"];
json_reader.seek_to(&path)?;
// Read the value to which the call seeked to
let value = json_reader.next_string()?;
values.push(value);
// Go back to original location to continue reading there
json_reader.seek_back(&path)?;
}
json_reader.end_array()?;
assert_eq!(values, vec!["first", "second"]);
§Panics
Panics may occur if not used according to the correct usage described above.