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

7.5 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]
    }
}

Select a pointer (or a node of the tree) to walk it through this document; each segment of the pointer goes one level deeper. The table below lists the same pointers.

Highlighted: the path of the pointer /nested/three/1, which identifies false.

  • root object
    • "array" array
      • 0: "A"
      • 1: "B"
      • 2: "C"
    • "nested" object
      • "one": 1
      • "two": 2
      • "three" array
        • 0: true
        • 1: false

The highlighted nodes are the path from the root to the selected level, and the line below the tree shows the value the pointer resolves to. Select a segment in the pointer bar to stop at a shallower level, or a node of the tree to select its pointer.

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

JSON Pointer JSON value
`` {"array":["A","B","C"],"nested":{"one":1,"two":2,"three":[true,false]}}
/array ["A","B","C"]
/array/0 A
/array/1 B
/array/2 C
/nested {"one":1,"two":2,"three":[true,false]}
/nested/one 1
/nested/two 2
/nested/three [true,false]
/nested/three/0 true
/nested/three/1 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.

URI fragment representation

RFC 6901, section 6 also defines a URI fragment identifier representation (#/a%20b). It is not supported: json::json_pointer("#/a") throws parse_error.107. 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.

Creating intermediate levels that don't exist

See the operator[] notes 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();

Each leaf of the document becomes one key of the flat object, and unflatten() reverses the mapping:

Left: the example document as a tree; right: the flat object it becomes. flatten() converts from left to right, unflatten() from right to left.

See also