119 lines
4.6 KiB
Markdown
119 lines
4.6 KiB
Markdown
# 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)`
|
|
1. `key("a")`
|
|
1. `start_array(-1)`
|
|
1. `number_unsigned(1)`
|
|
1. `boolean(true)`
|
|
1. `end_array()`
|
|
1. `key("b")`
|
|
1. `string("x")`
|
|
1. `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.
|
|
1. Create an object of your SAX interface class, e.g. `my_sax`.
|
|
1. 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
|
|
|
|
- [`json_sax`](https://json.nlohmann.me/api/json_sax/index.md) - documentation of the SAX interface
|
|
- [`sax_parse`](https://json.nlohmann.me/api/basic_json/sax_parse/index.md) - SAX parser
|
|
- [Parsing](https://json.nlohmann.me/features/parsing/index.md) - overview of the parsing functions
|
|
- [Parsing and Exceptions](https://json.nlohmann.me/features/parsing/parse_exceptions/index.md) - handling parse errors and locating them in the input
|
|
- [`parse`](https://json.nlohmann.me/api/basic_json/parse/index.md) - deserialize from a compatible input
|
|
- [Binary Formats](https://json.nlohmann.me/features/binary_formats/index.md) - CBOR, MessagePack, BSON, and other formats
|