Files
json/docs/mkdocs/docs/api/basic_json/sax_parse.md
T
Niels Lohmann 07aa3d1d69 docs: fix NaN ordering, FILE* locking and binary integer-range statements (#6088)
* docs: state that NaN ordering inside containers depends on the standard

When the element-wise comparison of arrays or objects reaches a NaN and
a number (or another NaN) before any other difference, the result
depends on the language standard. Before C++20 the pair counts as
equivalent and the following elements (or the sizes) decide, so
[1] <= [NaN] is true. Since C++20 the comparison is unordered and
<, <=, >, >= all yield false. Document this on operator<, <=, >, >=
and <=>.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* docs: fix the FILE* notes of parse() and the locking promise

The performance note of parse() said a FILE* is read one character at a
time. With glibc and the Apple C library the characters in the FILE's
buffer are scanned in bulk; only elsewhere is it one character at a
time. The file is locked once only where the C library has unlocked
stdio functions (not on musl, MinGW, newlib, with
JSON_DISABLE_UNLOCKED_FILE_IO, or under MSan). Qualify the promise on
parse.md, sax_parse.md, the parsing page and the performance page.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* docs: fix integer ranges in the MessagePack and BJData tables

number_integer_t is std::int64_t, so number_integer cannot hold values
above 9223372036854775807; those are number_unsigned. The MessagePack
row for uint 64 listed the range up to 18446744073709551615, and the
BJData table had a uint64 row for number_integer that can never be
selected. The CBOR table was already corrected.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* docs: name the macros that turn off FILE* locking and bulk scans

parse() and sax_parse() now say that the FILE* is locked unless
JSON_DISABLE_UNLOCKED_FILE_IO is defined to 1, and the input-source
table and the performance page name JSON_DISABLE_STREAM_BULK_SCAN and
JSON_DISABLE_UNLOCKED_FILE_IO with what each turns off.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-11-12 08:40:05 +01:00

8.2 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,
                      const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error);

// (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,
                      const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error);

Read from input and generate SAX events

  1. Read from a compatible input.

  2. 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 SentinelType differs from IteratorType, it must be comparable to the iterator type with operator!=.

    Ill-formed UTF-16 and UTF-32 sequences are rejected: a lone surrogate, a high surrogate that is not followed by its low surrogate, and a code point above U+10FFFF all yield a parse_error.101.

The SAX event lister must follow the interface of json_sax.

Template parameters

InputType
A compatible input, for instance:
  • an std::istream object
  • a FILE pointer
  • a C-style array of characters
  • a pointer to a null-terminated string of single byte characters
  • a std::string or a std::string_view (C++17)
  • a container obj for which begin(obj) and end(obj) produce a valid pair of iterators (as found via ADL or member functions, with semantics compatible to std::begin and std::end)
  • wide characters (wchar_t, char16_t, char32_t), which are converted to UTF-8: a wide string object (std::wstring, std::u16string, std::u32string) or an array (e.g. a wide string literal); a pointer to a null-terminated wide string (e.g. std::u16string::c_str()) is not supported
IteratorType
a compatible iterator type for overload (2); a pair of character iterators whose value_type is 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 to IteratorType via operator!=, for overload (2), for instance.
  • a custom sentinel type for C++20 ranges
  • std::default_sentinel_t, when IteratorType is std::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::json by default), see input_format_t for more information
strict (in)
whether the input has to be consumed completely (optional, #!cpp true by default); when #!cpp false and the input is a #!cpp std::istream, the character that terminates a number is consumed unless JSON_PRECISE_STREAM_POSITION is defined to 1; see operator>>
ignore_comments (in)
whether comments should be ignored and treated like whitespace (#!cpp true) or yield a parse error (#!cpp false); (optional, #!cpp false by 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 false by default)
tag_handler (in)
how to handle CBOR tags; see cbor_tag_handler_t. Ignored for formats other than CBOR (optional, cbor_tag_handler_t::error by 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

return value of the last processed SAX event

Exception safety

Strong guarantee: if an exception is thrown, there are no changes in the JSON value.

Exceptions

  • Throws parse_error.101 in case of an unexpected token, or empty input like a null FILE* or char* 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.

When reading from a #!c FILE* where the C library has unlocked stdio functions, the file is locked while it is parsed, unless JSON_DISABLE_UNLOCKED_FILE_IO is defined to 1. The lock is recursive, so the SAX handler may use the same file with stdio functions, but it must not wait for another thread that uses the same FILE object.

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_comments added in version 3.9.0.
  • Added ignore_trailing_commas in version 3.13.0.
  • Added tag_handler in version 3.13.0.
  • Extended container support (1) to include types with lvalue-only ADL begin/end (matching std::begin/std::end semantics) 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_POSITION added in version 3.13.0 to optionally leave a #!cpp std::istream positioned right after the parsed value when strict is #!cpp false.
  • Parsing from an std::istream scans the characters in its stream buffer in bulk in version 3.13.0 (JSON_DISABLE_STREAM_BULK_SCAN).
  • Parsing from a FILE* locks the file once instead of once per character in version 3.13.0 (JSON_DISABLE_UNLOCKED_FILE_IO).
  • Ill-formed UTF-16 and UTF-32 input (a lone surrogate, a high surrogate that is not followed by its low surrogate, or a code point above U+10FFFF) is rejected with parse_error.101 in version 3.13.0; before that, some such sequences were accepted or ended the input silently.

!!! 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);`.

See the [migration guide](../../integration/migration_guide.md#parsing) for how to update existing code.