| # <small>nlohmann::basic_json_view::</small>operator[] | |
| ```cpp | |
| // (1) | |
| basic_json_view operator[](string_view_t key) const; | |
| basic_json_view operator[](const char* key) const; | |
| basic_json_view operator[](const string_t& key) const; | |
| // (2) | |
| basic_json_view operator[](size_type idx) const; | |
| template<typename IntegerType> | |
| basic_json_view operator[](IntegerType idx) const; | |
| // (3) | |
| basic_json_view operator[](const json_pointer& ptr) const; | |
| ``` | |
| 1. Returns the value of the object member with key `key` — the first one, should the key occur more than once (see | |
| the [Notes](#notes) below) — or a [discarded](is_discarded.md) view if there is no such member. | |
| 2. Returns the array element at index `idx`, or a [discarded](is_discarded.md) view if `idx` is out of range. The | |
| template accepts every integer type except `#!cpp bool` and `#!cpp std::size_t` (`#!cpp int`, `#!cpp unsigned`, | |
| `#!cpp long`, `#!cpp std::int64_t`, ...) and forwards to the `size_type` overload, so that an integer argument is | |
| not ambiguous between that overload and 1; a negative `idx` is out of range. | |
| 3. Returns the value a JSON pointer `ptr` refers to, starting at this value, or a [discarded](is_discarded.md) view | |
| wherever resolving it further is not possible without inserting into or extending the document (see | |
| [Return value](#return-value) and [Exceptions](#exceptions) below). | |
| ## Parameters | |
| `key` (in) | |
| : object key of the element to access | |
| `idx` (in) | |
| : index of the element to access | |
| `ptr` (in) | |
| : JSON pointer to the element to access | |
| ## Return value | |
| 1. the value of the first member with key `key`, or a discarded view if no member has this key (or if this view is | |
| [discarded](is_discarded.md)) | |
| 2. the element at index `idx`, or a discarded view if `#!cpp idx >= size()` or `idx` is negative (or if this view is | |
| [discarded](is_discarded.md)) | |
| 3. the value `ptr` resolves to, starting at this value, or a discarded view (also if this view is | |
| [discarded](is_discarded.md)) for exactly the reference tokens where the | |
| **const** overload of [`BasicJsonType::operator[]`](../basic_json/operator%5B%5D.md) invokes undefined behavior for | |
| the same pointer and the same document: an object member that does not exist, or an array index that is out of | |
| range | |
| ## Exception safety | |
| Strong guarantee: there are no changes to the view or the document it refers to. | |
| ## Exceptions | |
| 1. Throws [`type_error.305`](../../home/exceptions.md#jsonexceptiontype_error305) if the value is not an object and | |
| not [discarded](is_discarded.md) — | |
| the same exception, with the same message, that the **const** overload of | |
| [`BasicJsonType::operator[]`](../basic_json/operator%5B%5D.md) throws for a string argument on a non-object value. | |
| 2. Throws [`type_error.305`](../../home/exceptions.md#jsonexceptiontype_error305) if the value is not an array and | |
| not [discarded](is_discarded.md) — | |
| the same exception, with the same message, that the **const** overload of | |
| [`BasicJsonType::operator[]`](../basic_json/operator%5B%5D.md) throws for a numeric argument on a non-array value. | |
| 3. Throws the same exceptions, with the same messages, that the **const** overload of | |
| [`BasicJsonType::operator[]`](../basic_json/operator%5B%5D.md) throws for the same pointer and the same document: | |
| - [`out_of_range.402`](../../home/exceptions.md#jsonexceptionout_of_range402) if a reference token is `#!cpp "-"` | |
| at an array. | |
| - [`out_of_range.404`](../../home/exceptions.md#jsonexceptionout_of_range404) if a reference token cannot be | |
| resolved because it is used on a primitive value. | |
| - [`parse_error.106`](../../home/exceptions.md#jsonexceptionparse_error106) if an array index in `ptr` begins | |
| with `#!cpp '0'`. | |
| - [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if an array index in `ptr` is not a | |
| number. | |
| None of these exceptions carry a [`JSON_DIAGNOSTICS`](../macros/json_diagnostics.md) path: the view has no | |
| `BasicJsonType` value to point at, so the exception is created without one, even if `BasicJsonType` was built with | |
| `JSON_DIAGNOSTICS` enabled. | |
| ## Complexity | |
| 1. Linear in the number of members: as for [`ordered_json`](../ordered_json.md), members are compared one after | |
| another, in document order, stopping at the first match. Each comparison first checks the | |
| key's length — already known from the index, without reading the key bytes — before comparing its content, so a | |
| key of a different length than `key` is rejected without touching the source text. | |
| Objects with 128 or more members get a hash index of their keys while parsing, so that a lookup in them takes | |
| constant time on average. | |
| 2. Linear in `idx`: elements are skipped one at a time from the first one, since they are not a fixed size in the | |
| index (unlike `BasicJsonType`'s array, which is random-access). Constant if no element of the array is an array | |
| or object, since the elements are then adjacent in the index. | |
| 3. Linear in the number of reference tokens of `ptr` and, for each token, in the number of members of the object at | |
| that level (as 1.) or the index into the array (as 2.). | |
| ## Notes | |
| Unlike `BasicJsonType::operator[]`, which is undefined behavior (guarded by a | |
| [runtime assertion](../../features/assertions.md)) for a missing key on a **const** value, this operator returns a | |
| safe, testable result for a missing key or an index out of range: a [discarded](is_discarded.md) view, which is | |
| tested with [`is_discarded`](is_discarded.md). | |
| There is also no non-const overload that inserts a missing key or extends an array — a view never modifies the | |
| document. | |
| !!! info "Chained access" | |
| `#!cpp operator[]` on a [discarded](is_discarded.md) view returns a discarded view and does not throw, so a chain | |
| like `#!cpp v["a"]["b"][0]` is safe even if `"a"` or `"b"` is missing: the first missing step makes the whole | |
| result discarded, which is tested once at the end. Type errors on values that are *not* discarded still throw: a | |
| key on an array or a primitive, or an index on an object or a primitive, is `type_error.305` as for | |
| `BasicJsonType`. [`at`](at.md) still throws for a discarded view, as it does for a missing key. | |
| !!! warning "Duplicate keys: the first member wins" | |
| If the source text has an object with a duplicate key, `#!cpp operator[]` (and [`at`](at.md), [`find`](find.md), | |
| [`contains`](contains.md), [`value`](value.md), and JSON pointer resolution) all resolve to | |
| the *first* member with that key, because a lookup can stop as soon as it finds a match. This is different from | |
| [`materialize()`](materialize.md) (and [`BasicJsonType::parse()`](../basic_json/parse.md)), which replay every | |
| member in order and so keep the *last* value for a repeated key, so `#!cpp v["a"]` and | |
| `#!cpp v.materialize()["a"]` can differ. To get the value `parse()` would give, use | |
| [`materialize()`](materialize.md) or iterate the members with [`items()`](items.md) and keep the last match. | |
| The key hash index of a larger object (128 members or more) leads to the first member of a key as well. | |
| [`begin()`](begin.md)/[`end()`](end.md) and [`items()`](items.md) iterate over *all* members, including | |
| duplicates, in document order. See [Duplicate keys](../../features/json_view.md#duplicate-keys) and | |
| [`size()`](size.md#notes). | |
| !!! info "JSON pointer resolution" | |
| Overload 3 walks `ptr` one reference token at a time, starting at this value, the same way [`at`](at.md) and | |
| [`contains`](contains.md) do. It only ever returns a discarded view where the **const** overload of | |
| `BasicJsonType::operator[]` would be undefined behavior for the same pointer — a missing object member or an | |
| out-of-range array index — and still throws for every other way `ptr` can fail to resolve. See | |
| [`at`](at.md#exceptions) for the checked version, which throws in every case instead, and | |
| [`contains`](contains.md) for a version that never throws. | |
| ## Examples | |
| ??? example "Example: (1)/(2) access specified element" | |
| The example below reads a couple of fields out of a batch of user records without ever materializing a full | |
| `BasicJsonType` value for the batch. `operator[]` is used both to look up an optional object member and to index | |
| into an array — in both cases, a missing value comes back as a discarded view that can be tested with a plain | |
| `#!cpp if`, instead of relying on undefined behavior. | |
| ```cpp | |
| #include <iostream> | |
| #include <nlohmann/json_view.hpp> | |
| using nlohmann::json_document; | |
| int main() | |
| { | |
| // two user records from a large API response; only the fields that are | |
| // actually read are ever touched, and no nlohmann::json tree is built | |
| // for the batch | |
| json_document batch = json_document::parse(R"( | |
| [ | |
| {"name": "Alice", "email": "alice@example.com", "tags": ["admin", "ops"]}, | |
| {"name": "Bob", "tags": []} | |
| ] | |
| )"); | |
| const auto users = batch.root(); | |
| for (std::size_t i = 0; i < users.size(); ++i) | |
| { | |
| const auto user = users[i]; | |
| std::cout << user["name"].materialize().dump(); | |
| // operator[] on a missing object key gives a discarded view -- test | |
| // it with is_discarded(). The const overload of json::operator[] | |
| // would instead be undefined behavior (guarded by an assertion) for | |
| // a missing key | |
| const auto email = user["email"]; | |
| if (!email.is_discarded()) | |
| { | |
| std::cout << " <" << email.materialize().dump() << ">"; | |
| } | |
| // the same holds for an array index past the end: a discarded view, | |
| // not undefined behavior | |
| const auto first_tag = user["tags"][0]; | |
| if (!first_tag.is_discarded()) | |
| { | |
| std::cout << " #" << first_tag.materialize().dump(); | |
| } | |
| std::cout << '\n'; | |
| } | |
| } | |
| ``` | |
| Output: | |
| ```json | |
| "Alice" <"alice@example.com"> #"admin" | |
| "Bob" | |
| ``` | |
| ??? example "Example: (3) access specified element via JSON pointer" | |
| The example below reaches straight into one deeply nested field of a large document with a single JSON pointer, | |
| without ever building a tree for the rest of it, and shows the discarded-view and throwing outcomes of a pointer | |
| that cannot be fully resolved. | |
| ```cpp | |
| #include <iostream> | |
| #include <nlohmann/json_view.hpp> | |
| using nlohmann::json_document; | |
| using json_pointer = nlohmann::json::json_pointer; | |
| int main() | |
| { | |
| // a larger document; operator[] with a JSON pointer reaches straight to | |
| // one deeply nested field, without ever building a tree for the rest | |
| json_document doc = json_document::parse(R"( | |
| { | |
| "region": { | |
| "servers": [ | |
| {"name": "eu-1", "metrics": {"cpu": 0.42}}, | |
| {"name": "eu-2", "metrics": {"cpu": 0.71}} | |
| ] | |
| } | |
| } | |
| )"); | |
| const auto root = doc.root(); | |
| std::cout << root[json_pointer("/region/servers/1/metrics/cpu")].materialize().dump() << '\n'; | |
| // a missing key or an out-of-range index along the path gives a | |
| // discarded view, exactly where const json::operator[] would be | |
| // undefined behavior for the same pointer | |
| const auto missing = root[json_pointer("/region/servers/5/metrics/cpu")]; | |
| if (!missing.is_discarded()) | |
| { | |
| std::cout << missing.materialize().dump() << '\n'; | |
| } | |
| else | |
| { | |
| std::cout << "no such server\n"; | |
| } | |
| // indexing into a primitive still throws, as basic_json::operator[] | |
| // does for the same pointer | |
| try | |
| { | |
| static_cast<void>(root[json_pointer("/region/servers/0/name/x")]); | |
| } | |
| catch (const nlohmann::json::out_of_range& e) | |
| { | |
| std::cout << e.what() << '\n'; | |
| } | |
| } | |
| ``` | |
| Output: | |
| ```json | |
| 0.71 | |
| no such server | |
| [json.exception.out_of_range.404] unresolved reference token 'x' | |
| ``` | |
| ## See also | |
| - [`at`](at.md) - access specified element with bounds checking (throws instead of returning a discarded view) | |
| - [`front`](front.md), [`back`](back.md) - access the first or last element | |
| - [`find`](find.md), [`contains`](contains.md) - look up a member without throwing | |
| - [`BasicJsonType::operator[]`](../basic_json/operator%5B%5D.md) - the corresponding function of `basic_json` | |
| - [`json_pointer`](../json_pointer/index.md) - JSON pointer type used by overload 3 | |
| ## Version history | |
| - Added in version 3.13.0. |