Files
json/docs/mkdocs/docs/features/json_pointer.md
T
Niels Lohmann c20b6eddf4 docs: correct JSON Pointer documentation and add tests (#5937)
Fix inaccurate or missing statements about unflatten (third round-trip
failure, empty token, typo), value (type_error.306 before pointer lookup),
contains (pointer overload), parent_pointer and operator<< (bad_alloc),
out_of_range.410 example, template parameter requirements (resize(n)), and
document the URI fragment form and non-unique member names of RFC 6901.
Add tests for the unflatten and value() cases.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-26 17:11:46 +01:00

5.8 KiB

JSON Pointer

Introduction

The library supports JSON Pointer (RFC 6901) as an alternative means to address structured values. A JSON Pointer is a string that identifies a specific value within a JSON document.

Consider the following JSON document

{
    "array": ["A", "B", "C"],
    "nested": {
        "one": 1,
        "two": 2,
        "three": [true, false]
    }
}

Then every value inside the JSON document can be identified as follows:

JSON Pointer JSON value
`` #!json {"array":["A","B","C"],"nested":{"one":1,"two":2,"three":[true,false]}}
/array #!json ["A","B","C"]
/array/0 #!json A
/array/1 #!json B
/array/2 #!json C
/nested #!json {"one":1,"two":2,"three":[true,false]}
/nested/one #!json 1
/nested/two #!json 2
/nested/three #!json [true,false]
/nested/three/0 #!json true
/nested/three/1 #!json false

Note / does not identify the root (i.e., the whole document), but an object entry with empty key "". See RFC 6901 for more information.

RFC 6901, section 4 states that evaluation fails if an object has non-unique member names. A basic_json object holds one value per key (see object_t for how duplicate keys are handled while parsing), so evaluating a JSON Pointer never encounters duplicates.

JSON Pointer creation

JSON Pointers can be created from a string:

json::json_pointer p("/nested/one");

Furthermore, a user-defined string literal can be used to achieve the same result:

auto p = "/nested/one"_json_pointer;

The escaping rules of RFC 6901 are implemented. See the constructor documentation for more information.

!!! note "URI fragment representation"

[RFC 6901, section 6](https://tools.ietf.org/html/rfc6901#section-6) also defines a URI fragment identifier
representation (`#/a%20b`). It is not supported: `#!cpp json::json_pointer("#/a")` throws
[`parse_error.107`](../home/exceptions.md#jsonexceptionparse_error107). Strip the leading `#` and
percent-decode the remainder before creating the JSON pointer.

Value access

JSON Pointers can be used in the at, operator[], and value functions just like object keys or array indices.

// the JSON value from above
auto j = json::parse(R"({
    "array": ["A", "B", "C"],
    "nested": {
        "one": 1,
        "two": 2,
        "three": [true, false]
    }
})");

// access values
auto val = j[""_json_pointer];                              // {"array":["A","B","C"],...}
auto val1 = j["/nested/one"_json_pointer];                  // 1
auto val2 = j.at(json::json_pointer("/nested/three/1"));    // false
auto val3 = j.value(json::json_pointer("/nested/four"), 0); // 0

To read a value with a fallback, use value with a JSON Pointer; to test for existence, use contains. Neither needs intermediate checks, see Nested values.

!!! note "Creating intermediate levels that don't exist"

See the [`operator[]` notes](../api/basic_json/operator%5B%5D.md#return-value) for how array vs. object is
decided when a pointer creates intermediate levels that don't exist yet.

Flatten / unflatten

The library implements a function flatten to convert any JSON document into a JSON object where each key is a JSON Pointer and each value is a primitive JSON value (i.e., a string, boolean, number, or null).

// the JSON value from above
auto j = json::parse(R"({
    "array": ["A", "B", "C"],
    "nested": {
        "one": 1,
        "two": 2,
        "three": [true, false]
    }
})");

// create flattened value
auto j_flat = j.flatten();

The resulting value j_flat is:

{
  "/array/0": "A",
  "/array/1": "B",
  "/array/2": "C",
  "/nested/one": 1,
  "/nested/two": 2,
  "/nested/three/0": true,
  "/nested/three/1": false
}

The reverse function, unflatten recreates the original value.

auto j_original = j_flat.unflatten();

See also