The return value of json_sax::parse_error() was documented both as "must return false" and as "whether the parsing should continue", and the code just passed it on. For JSON text, parsing stopped anyway, but sax_parse() could report success for invalid input. The binary readers read on after the error, looping forever on a CBOR indefinite-length array without its end. Now false stops parsing, and true recovers from the error: - JSON text is repaired with the smallest local edit (insert a missing ',' or ':', remove a stray token, keep the readable part of a broken string or number, null for a value that cannot be read, close the innermost container at a wrong closing bracket and all of them at the end of the input), and parsing continues. The SAX events stay balanced, every key is followed by exactly one value, and each token is reported at most once. - The binary formats cannot resynchronize, so they stop, but complete the value read so far. sax_parse() returns false after any error. parse(), accept(), and the from_*() functions never recover and compile to the same code as before. Supersedes #4522. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
5.9 KiB
nlohmann::basic_json::sax_parse
// (1)
template <typename InputType, typename SAX>
static bool sax_parse(InputType&& i,
SAX* sax,
input_format_t format = input_format_t::json,
const bool strict = true,
const bool ignore_comments = false,
const bool ignore_trailing_commas = false);
// (2)
template<class IteratorType, class SAX, class SentinelType = IteratorType>
static bool sax_parse(IteratorType first, SentinelType last,
SAX* sax,
input_format_t format = input_format_t::json,
const bool strict = true,
const bool ignore_comments = false,
const bool ignore_trailing_commas = false);
Read from input and generate SAX events
-
Read from a compatible input.
-
Read from a pair of character iterators, or an iterator and a sentinel of a different type (C++20 ranges support)
The value_type of the iterator must be an integral type with a size of 1, 2, or 4 bytes, which will be interpreted respectively as UTF-8, UTF-16, and UTF-32. If
SentinelTypediffers fromIteratorType, it must be comparable to the iterator type withoperator!=.
The SAX event lister must follow the interface of json_sax.
Template parameters
InputType- A compatible input, for instance:
- an
std::istreamobject - a
FILEpointer - a C-style array of characters
- a pointer to a null-terminated string of single byte characters
- a container
objfor whichbegin(obj)andend(obj)produce a valid pair of iterators (as found via ADL or member functions, with semantics compatible tostd::beginandstd::end)
- an
IteratorType- a compatible iterator type for overload (2); a pair of character iterators whose
value_typeis an integral type with a size of 1, 2, or 4 bytes (interpreted respectively as UTF-8, UTF-16, and UTF-32) SentinelType- defaults to
IteratorType; may be a different type comparable toIteratorTypeviaoperator!=, for overload (2), for instance.- a custom sentinel type for C++20 ranges
std::default_sentinel_t, whenIteratorTypeisstd::counted_iterator
SAX- a class fulfilling the SAX event listener interface; see
json_sax
Parameters
i(in)- Input to parse from
sax(in)- SAX event listener (must not be null)
format(in)- the format to parse (JSON, BJData, BON8, BSON, CBOR, MessagePack, or UBJSON) (optional,
input_format_t::jsonby default), seeinput_format_tfor more information strict(in)- whether the input has to be consumed completely (optional,
#!cpp trueby default); when#!cpp falseand the input is a#!cpp std::istream, the character that terminates a number is consumed unlessJSON_PRECISE_STREAM_POSITIONis defined to1; seeoperator>> ignore_comments(in)- whether comments should be ignored and treated like whitespace (
#!cpp true) or yield a parse error (#!cpp false); (optional,#!cpp falseby default) ignore_trailing_commas(in)- whether trailing commas in arrays or objects should be ignored and treated like whitespace (
#!cpp true) or yield a parse error (#!cpp false); (optional,#!cpp falseby default) first(in)- iterator to the start of a character range
last(in)- iterator to the end of a character range, or a sentinel value that compares equal to the end iterator with
operator!=
Return value
#!cpp true if the input was parsed without errors and no SAX event returned #!cpp false; #!cpp false otherwise.
In particular, the result is #!cpp false for input with errors, even if the SAX parser recovered from all of them
(see error recovery).
Exception safety
Strong guarantee: if an exception is thrown, there are no changes in the JSON value.
Exceptions
- Throws
parse_error.101in case of an unexpected token, or empty input like a nullFILE*orchar*pointer.
Complexity
Linear in the length of the input. The parser is a predictive LL(1) parser. The complexity can be higher if the SAX
consumer sax has a super-linear complexity.
Notes
A UTF-8 byte order mark is silently ignored.
Examples
??? example
The example below demonstrates the `sax_parse()` function reading from string and processing the events with a
user-defined SAX event consumer.
```cpp
--8<-- "examples/sax_parse.cpp"
```
Output:
```json
--8<-- "examples/sax_parse.output"
```
See also
Version history
- Added in version 3.2.0.
- Ignoring comments via
ignore_commentsadded in version 3.9.0. - Added
ignore_trailing_commasin version 3.13.0. - Extended container support (1) to include types with lvalue-only ADL
begin/end(matchingstd::begin/std::endsemantics) in version 3.13.0. - Recovering from parse errors (see
parse_error) added in version 3.13.0. - Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0.
JSON_PRECISE_STREAM_POSITIONadded in version 3.13.0 to optionally leave a#!cpp std::istreampositioned right after the parsed value whenstrictis#!cpp false.
!!! warning "Deprecation"
Overload (2) replaces calls to `sax_parse` with a pair of iterators as their first parameter which has been
deprecated in version 3.8.0. This overload will be removed in version 4.0.0. Please replace all calls like
`#!cpp sax_parse({ptr, ptr+len});` with `#!cpp sax_parse(ptr, ptr+len);`.