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

4.9 KiB

Element Access

There are many ways elements in a JSON value can be accessed:

Testing whether a key or index exists before accessing it is also possible, with contains or find (which returns an iterator to the value, or end() if it is not found).

How do I get a value out? Start at the top and follow the first question that applies:

flowchart TD
    A["getting a value out"] --> P{{"nested path such as /server/port?"}}
    P -->|"yes"| JP["JSON Pointer: at(ptr), value(ptr, default), contains(ptr)"]
    P -->|"no, one key or index"| T{{"only testing whether it exists?"}}
    T -->|"yes"| CF["contains() / find()"]
    T -->|"no"| M{{"may it be missing?"}}
    M -->|"yes, a fallback is fine"| V["value(key, default)"]
    M -->|"yes, and missing is an error"| AT["at(): throws out_of_range"]
    M -->|"no, it exists and its type is known"| OP["operator[] and get#lt;T#gt;()"]
    OP -.- W["non-const operator[] inserts null for a missing key"]

Decision tree for reading a value: the labels on the arrows are the answers to the questions, and the boxes name the functions to use. The dashed line marks a side effect of the non-const operator[].

Does this key exist?

Use contains to test for a key; it does not modify the value and does not throw:

json j = {{"name", "Mary"}, {"address", {{"city", "Berlin"}}}};

j.contains("name");                   // true
j.contains("age");                    // false
j.contains("city");                   // false: contains() only looks at the top level
j["address"].contains("city");        // true
j.contains(json::json_pointer("/address/city"));  // true: a JSON pointer tests a nested path in one call

If the value is needed afterwards, find tests and accesses with a single lookup:

if (auto it = j.find("name"); it != j.end())
{
    std::cout << *it << '\n';
}

contains also returns true for a key whose value is null; use j.contains("k") && !j["k"].is_null() if a null should count as missing. To read a value with a fallback instead, see value.

operator[] inserts missing keys

Like std::map::operator[], the non-const operator[] adds a null value if the key is missing. Testing a key with it therefore changes the object:

json j = {{"foo", 1}};
bool absent = j["bar"].is_null();   // true, but j is now {"bar": null, "foo": 1}

Use contains/find to test, and at to access a value that must exist (it throws an out_of_range exception otherwise).

See also