Files
json/features/parsing/sax_interface/index.md
T
2026-10-27 12:14:00 +00:00

4.6 KiB

SAX Interface

The library uses a SAX-like interface with the following functions:

classDiagram

class sax_t ["json::sax_t"] {
    <<interface>>
    +bool null()*

    +bool boolean(bool val)*

    +bool number_integer(number_integer_t val)*
    +bool number_unsigned(number_unsigned_t val)*

    +bool number_float(number_float_t val, const string_t& s)*

    +bool string(string_t& val)*
    +bool binary(binary_t& val)*

    +bool start_object(std::size_t elements)*
    +bool end_object()*
    +bool start_array(std::size_t elements)*
    +bool end_array()*
    +bool key(string_t& val)*

    +bool parse_error(std::size_t position, const std::string& last_token, const json::exception& ex)*
}

The interface json::sax_t: one function per event, each returning bool; the functions marked with * are pure virtual.

// called when null is parsed
bool null();

// called when a boolean is parsed; value is passed
bool boolean(bool val);

// called when a signed or unsigned integer number is parsed; value is passed
bool number_integer(number_integer_t val);
bool number_unsigned(number_unsigned_t val);

// called when a floating-point number is parsed; value and original string is passed
bool number_float(number_float_t val, const string_t& s);

// called when a string is parsed; value is passed and can be safely moved away
bool string(string_t& val);
// called when a binary value is parsed; value is passed and can be safely moved away
bool binary(binary_t& val);

// called when an object or array begins or ends, resp. The number of elements is passed (or -1 if not known)
bool start_object(std::size_t elements);
bool end_object();
bool start_array(std::size_t elements);
bool end_array();
// called when an object key is parsed; value is passed and can be safely moved away
bool key(string_t& val);

// called when a parse error occurs; byte position, the last token, and an exception is passed
bool parse_error(std::size_t position, const std::string& last_token, const json::exception& ex);

The return value of each function determines whether parsing should proceed.

Stepping through the events

The events for a small input, step by step, and what two different handlers do with them. Press Play or step with Next:

input

{"a":[1,true],"b":"x"}

events, in the order the parser calls them

  1. start_object(-1)
  2. key("a")
  3. start_array(-1)
  4. number_unsigned(1)
  5. boolean(true)
  6. end_array()
  7. key("b")
  8. string("x")
  9. end_object()

handler: build a value tree, as parse does

{
  "a": [
    1,
    true
  ],
  "b": "x"
}

After end_object() the tree is complete and no container is open. The number of elements is passed as -1: the parser does not know it in advance.

The three lanes show the input consumed so far, the events called so far, and the state of the selected handler (build a tree or keep only /b). Check return false at this event to stop the parse at the current event and see which events are no longer called.

To implement your own SAX handler, proceed as follows:

  1. Implement the SAX interface in a class. You can use class nlohmann::json_sax<json> as base class, but you can also use any class where the functions described above are implemented and public.
  2. Create an object of your SAX interface class, e.g. my_sax.
  3. Call bool json::sax_parse(input, &my_sax); where the first parameter can be any input like a string or an input stream and the second parameter is a pointer to your SAX interface.

Note the sax_parse function only returns a bool indicating the result of the last executed SAX event. It does not return json value - it is up to you to decide what to do with the SAX events. Furthermore, no exceptions are thrown in case of a parse error - it is up to you what to do with the exception object passed to your parse_error implementation. Internally, the SAX interface is used for the DOM parser (class json_sax_dom_parser) as well as the acceptor (json_sax_acceptor), see file json_sax.hpp.

See also