Skip to content

JSON_DIAGNOSTIC_POSITIONS

#define JSON_DIAGNOSTIC_POSITIONS /* value */

This macro enables position diagnostics for generated JSON objects.

When enabled, two new properties: start_pos() and end_pos() are added to nlohmann::basic_json objects and fields. start_pos() returns the start position of that JSON object/field in the original string the object was parsed from. Likewise, end_pos() returns the end position of that JSON object/field in the original string the object was parsed from.

start_pos() returns the first character of a given element in the original JSON string, while end_pos() returns the character following the last character. For objects and arrays, the first and last characters correspond to the opening or closing braces/brackets, respectively. For fields, the first and last character represent the opening and closing quotes or the first and last character of the field's numerical or predefined value (true/false/null), respectively.

Given the above, end_pos() - start_pos() for an object or field provides the length of the string representation for that object or field, including the opening or closing braces, brackets, or quotes.

start_pos() and end_pos() are only set if the JSON object was parsed using parse(). For all other cases, std::string::npos will be returned.

Note that enabling this macro increases the size of every JSON value by two std::size_t fields and adds slight runtime overhead.

Default definition

The default value is 0 (position diagnostics are switched off).

#define JSON_DIAGNOSTIC_POSITIONS 0

When the macro is not defined, the library will define it to its default value.

Notes

CMake option

Diagnostic messages can also be controlled with the CMake option JSON_Diagnostic_Positions (OFF by default) which defines JSON_DIAGNOSTIC_POSITIONS accordingly.

Examples

Example 1: retrieving positions
#include <iostream>

#define JSON_DIAGNOSTIC_POSITIONS 1
#include <nlohmann/json.hpp>

using json = nlohmann::json;

int main()
{
    std::string json_string = R"(
    {
        "address": {
            "street": "Fake Street",
            "housenumber": 1
        }
    }
    )";
    json j = json::parse(json_string);

    std::cout << "Root diagnostic positions: \n";
    std::cout << "\tstart_pos: " << j.start_pos() << '\n';
    std::cout << "\tend_pos:" << j.end_pos() << "\n";
    std::cout << "Original string: \n";
    std::cout << "{\n        \"address\": {\n            \"street\": \"Fake Street\",\n            \"housenumber\": 1\n        }\n    }" << "\n";
    std::cout << "Parsed string: \n";
    std::cout << json_string.substr(j.start_pos(), j.end_pos() - j.start_pos()) << "\n\n";

    std::cout << "address diagnostic positions: \n";
    std::cout << "\tstart_pos:" << j["address"].start_pos() << '\n';
    std::cout << "\tend_pos:" << j["address"].end_pos() << "\n\n";
    std::cout << "Original string: \n";
    std::cout << "{            \"street\": \"Fake Street\",\n            \"housenumber\": 1\n        }" << "\n";
    std::cout << "Parsed string: \n";
    std::cout << json_string.substr(j["address"].start_pos(), j["address"].end_pos() - j["address"].start_pos()) << "\n\n";

    std::cout << "street diagnostic positions: \n";
    std::cout << "\tstart_pos:" << j["address"]["street"].start_pos() << '\n';
    std::cout << "\tend_pos:" << j["address"]["street"].end_pos() << "\n\n";
    std::cout << "Original string: \n";
    std::cout << "\"Fake Street\"" << "\n";
    std::cout << "Parsed string: \n";
    std::cout << json_string.substr(j["address"]["street"].start_pos(), j["address"]["street"].end_pos() - j["address"]["street"].start_pos()) << "\n\n";

    std::cout << "housenumber diagnostic positions: \n";
    std::cout << "\tstart_pos:" << j["address"]["housenumber"].start_pos() << '\n';
    std::cout << "\tend_pos:" << j["address"]["housenumber"].end_pos() << "\n\n";
    std::cout << "Original string: \n";
    std::cout << "1" << "\n";
    std::cout << "Parsed string: \n";
    std::cout << json_string.substr(j["address"]["housenumber"].start_pos(), j["address"]["housenumber"].end_pos() - j["address"]["housenumber"].start_pos()) << "\n\n";
}

Output:

Root diagnostic positions: 
    start_pos: 5
    end_pos:109
Original string: 
{
        "address": {
            "street": "Fake Street",
            "housenumber": 1
        }
    }
Parsed string: 
{
        "address": {
            "street": "Fake Street",
            "housenumber": 1
        }
    }

address diagnostic positions: 
    start_pos:26
    end_pos:103

Original string: 
{            "street": "Fake Street",
            "housenumber": 1
        }
Parsed string: 
{
            "street": "Fake Street",
            "housenumber": 1
        }

street diagnostic positions: 
    start_pos:50
    end_pos:63

Original string: 
"Fake Street"
Parsed string: 
"Fake Street"

housenumber diagnostic positions: 
    start_pos:92
    end_pos:93

Original string: 
1
Parsed string: 
1

The output shows the start/end positions of all the objects and fields in the JSON string.

Version history