Skip to content

# Parser Callbacks

## Overview

With a parser callback function, the result of parsing a JSON text can be influenced. When passed to `parse`, it is called on certain events (passed as `parse_event_t` via parameter `event`) with a set recursion depth `depth` and context JSON value `parsed`. The return value of the callback function is a boolean indicating whether the element that emitted the callback shall be kept or not.

The type of the callback function is:

    template<typename BasicJsonType>
    using parser_callback_t =
        std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;

## Callback event types

We distinguish six scenarios (determined by the event type) in which the callback function can be called. The following table describes the values of the parameters `depth`, `event`, and `parsed`.

parameter `event` | description | parameter `depth` | parameter `parsed`
--- | --- | --- | ---
`parse_event_t::object_start` | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded
`parse_event_t::key` | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key
`parse_event_t::object_end` | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object
`parse_event_t::array_start` | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded
`parse_event_t::array_end` | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array
`parse_event_t::value` | the parser finished reading a JSON value | depth of the value | the parsed JSON value

Example

When parsing the following JSON text,

    {
        "name": "Berlin",
        "location": [
            52.519444,
            13.406667
        ]
    }

these calls are made to the callback function:

event | depth | parsed
--- | --- | ---
`object_start` | 0 | discarded
`key` | 1 | `"name"`
`value` | 1 | `"Berlin"`
`key` | 1 | `"location"`
`array_start` | 1 | discarded
`value` | 2 | `52.519444`
`value` | 2 | `13.406667`
`array_end` | 1 | `[52.519444,13.406667]`
`object_end` | 0 | `{"location":[52.519444,13.406667],"name":"Berlin"}`

## Return value

Discarding a value (i.e., returning `false`) has different effects depending on the context in which function was called:

- Discarded values in structured types are skipped. That is, the parser will behave as if the discarded value was never read.
- In case a value outside a structured type is skipped, it is replaced with `null`. This case happens if the top-level element is skipped.

Example

The example below demonstrates the `parse()` function with and without callback function.

    #include <iostream>
    #include <iomanip>
    #include <nlohmann/json.hpp>

    using json = nlohmann::json;

    int main()
    {
        // a JSON text
        auto text = R"(
        {
            "Image": {
                "Width":  800,
                "Height": 600,
                "Title":  "View from 15th Floor",
                "Thumbnail": {
                    "Url":    "http://www.example.com/image/481989943",
                    "Height": 125,
                    "Width":  100
                },
                "Animated" : false,
                "IDs": [116, 943, 234, 38793]
            }
        }
        )";

        // parse and serialize JSON
        json j_complete = json::parse(text);
        std::cout << std::setw(4) << j_complete << "\n\n";

        // define parser callback
        json::parser_callback_t cb = [](int depth, json::parse_event_t event, json & parsed)
        {
            // skip object elements with key "Thumbnail"
            if (event == json::parse_event_t::key and parsed == json("Thumbnail"))
            {
                return false;
            }
            else
            {
                return true;
            }
        };

        // parse (with callback) and serialize JSON
        json j_filtered = json::parse(text, cb);
        std::cout << std::setw(4) << j_filtered << '\n';
    }

Output:

    {
        "Image": {
            "Animated": false,
            "Height": 600,
            "IDs": [
                116,
                943,
                234,
                38793
            ],
            "Thumbnail": {
                "Height": 125,
                "Url": "http://www.example.com/image/481989943",
                "Width": 100
            },
            "Title": "View from 15th Floor",
            "Width": 800
        }
    }

    {
        "Image": {
            "Animated": false,
            "Height": 600,
            "IDs": [
                116,
                943,
                234,
                38793
            ],
            "Title": "View from 15th Floor",
            "Width": 800
        }
    }