Files
json/docs/mkdocs/docs/api/basic_json/operator[].md
T
Niels Lohmann 81d66291c5 Create objects for pointer tokens that cannot be array indices (#5358)
* create objects for tokens that cannot be array indices (#5357)

When operator[](json_pointer) traverses a level that does not exist yet,
the null value is turned into an array or an object depending on the
reference token. The check only tested whether all characters are digits,
so tokens that can never be a valid array index selected an array and
then failed:

- "01" (and any other token with a leading '0') threw parse_error.106
- the empty token threw out_of_range.404

Both tokens are valid object keys, and both work when the level already
exists as an object, so creating the level changed the outcome. Test the
token against the RFC 6901, Sect. 4 grammar for array indices instead, so
that such tokens create an object. This only affects pointers that threw
before.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* Clarify that the token 0 is a valid array index in operator[] docs

The note described valid array indices as "a nonempty sequence of digits
without a leading 0", which read literally excludes the token "0" itself,
contradicting both the code and the /foo/0/0/0 example in the next
sentence. Spell out the RFC 6901 grammar instead.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

---------

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

12 KiB

nlohmann::basic_json::operator[]

// (1)
reference operator[](size_type idx);
const_reference operator[](size_type idx) const;

// (2)
reference operator[](typename object_t::key_type key);
const_reference operator[](const typename object_t::key_type& key) const;

// (3)
template<typename KeyType>
reference operator[](KeyType&& key);
template<typename KeyType>
const_reference operator[](KeyType&& key) const;

// (4)
reference operator[](const json_pointer& ptr);
const_reference operator[](const json_pointer& ptr) const;
  1. Returns a reference to the array element at specified location idx.
  2. Returns a reference to the object element with specified key key. The non-const qualified overload takes the key by value.
  3. See 2. This overload is only available if KeyType is comparable with #!cpp typename object_t::key_type and #!cpp typename object_comparator_t::is_transparent denotes a type.
  4. Returns a reference to the element with specified JSON pointer ptr.

Template parameters

KeyType
A type for an object key other than json_pointer that is comparable with string_t using object_comparator_t. This can also be a string view (C++17).

Iterator invalidation

For the non-const versions 1. and 4., when passing an array index that does not exist, it is created and filled with a #!json null value before a reference to it is returned. For this, a reallocation can happen, in which case all iterators (including the end() iterator) and all references to the elements are invalidated.

For ordered_json, also passing an object key to the non-const versions 2., 3., and 4., a reallocation can happen which again invalidates all iterators and all references.

Parameters

idx (in)
index of the element to access
key (in)
object key of the element to access
ptr (in)
JSON pointer to the desired element

Return value

  1. (const) reference to the element at index idx
  2. (const) reference to the element at key key
  3. (const) reference to the element at key key
  4. (const) reference to the element pointed to by ptr

Exception safety

Strong exception safety: if an exception occurs, the original value stays intact.

Exceptions

  1. The function can throw the following exceptions:

    • Throws type_error.305 if the JSON value is not an array or null; in that case, using the [] operator with an index makes no sense.
    • Throws #!cpp std::length_error if idx equals the maximum value of size_type; the array is left unchanged. (This is the one index for which growing the array to hold it cannot be expressed as a size_type size, the same way an oversized resize throws.)
  2. The function can throw the following exceptions:

    • Throws type_error.305 if the JSON value is not an object or null; in that case, using the [] operator with a key makes no sense.
  3. See 2.

  4. The function can throw the following exceptions:

    • Throws parse_error.106 if an array index in the passed JSON pointer ptr begins with '0'.
    • Throws parse_error.109 if an array index in the passed JSON pointer ptr is not a number.
    • Throws out_of_range.402 if the array index '-' is used in the passed JSON pointer ptr for the const version.
    • Throws out_of_range.404 if the JSON pointer ptr can not be resolved.
    • Throws out_of_range.410 if an array index in the passed JSON pointer ptr exceeds the range of size_type (e.g., on 32-bit platforms).

    For the const version, an object key or array index in ptr that does not exist is not reported by an exception, but is undefined behavior (see the notes below). Use at for checked access.

Complexity

  1. Constant if idx is in the range of the array. Otherwise, linear in idx - size().
  2. Logarithmic in the size of the container.
  3. Logarithmic in the size of the container.
  4. Logarithmic in the size of the container.

Notes

!!! danger "Undefined behavior and runtime assertions"

The following cases apply to the **const** overloads; the non-const overloads instead insert the missing element
(see the notes below).

1. If the element at index `idx` does not exist, the behavior is undefined and is **guarded by a
   [runtime assertion](../../features/assertions.md)**!
2. If the element with key `key` does not exist, the behavior is undefined and is **guarded by a
   [runtime assertion](../../features/assertions.md)**!
3. If the JSON pointer `ptr` refers to an object key or an array index that does not exist, the behavior is
   undefined and is **guarded by a [runtime assertion](../../features/assertions.md)**!
  1. The non-const version may add values: If idx is beyond the range of the array (i.e., idx >= size()), then the array is silently filled up with #!json null values to make idx a valid reference to the last stored element. In case the value was #!json null before, it is converted to an array.

  2. If key is not found in the object, then it is silently added to the object and filled with a #!json null value to make key a valid reference. In case the value was #!json null before, it is converted to an object.

  3. See 2.

  4. null values are created in arrays and objects if necessary.

    In particular:

    • If the JSON pointer points to an object key that does not exist, it is created and filled with a #!json null value before a reference to it is returned.
    • If the JSON pointer points to an array index that does not exist, it is created and filled with a #!json null value before a reference to it is returned. All indices between the current maximum and the given index are also filled with #!json null.
    • The special value - is treated as a synonym for the index past the end.

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

     When the JSON pointer traverses intermediate levels that don't exist at all yet (not just a missing
     leaf), each missing level is created as an array or an object depending on whether the corresponding
     pointer token is a valid array index: the token `0`, a sequence of digits that does not begin with `0`,
     or the token `-` creates an array, and every other token creates an object. For example, on an
     initially `#!json null` value, `/foo/0/0/0` creates nested arrays, while `/foo/one/one/one` creates
     nested objects. Tokens such as `01` or the empty token cannot be array indices (cf. RFC 6901, Sect. 4)
     and therefore create objects, just as they would if the level already existed as an object. This is not
     specified by the JSON Pointer RFC; it is this library's own, intentional disambiguation rule. See also
     [JSON Pointer](../../features/json_pointer.md).
    

!!! warning "Deprecation"

Overload (4) also accepts a [`json_pointer`](../json_pointer/index.md) whose template argument is a `basic_json`
specialization (e.g., `nlohmann::json_pointer<nlohmann::json>`) instead of a string type. This is deprecated since
version 3.11.0 and will be removed in a future major version; use `basic_json::json_pointer` (for `json`,
`nlohmann::json_pointer<std::string>`) instead.

You should be warned by your compiler with a `-Wdeprecated-declarations` warning if you are using a deprecated
function.

See the [migration guide](../../integration/migration_guide.md#json-pointers) for how to update existing code.

Examples

??? example "Example: (1) access specified array element"

The example below shows how array elements can be read and written using `[]` operator. Note the addition of
`#!json null` values.
    
```cpp
--8<-- "examples/operator_array__size_type.cpp"
```

Output:

```json
--8<-- "examples/operator_array__size_type.output"
```

??? example "Example: (1) access specified array element (const)"

The example below shows how array elements can be read using the `[]` operator.

```cpp
--8<-- "examples/operator_array__size_type_const.cpp"
```

Output:

```json
--8<-- "examples/operator_array__size_type_const.output"
```

??? example "Example: (2) access specified object element"

The example below shows how object elements can be read and written using the `[]` operator.

```cpp
--8<-- "examples/operator_array__object_t_key_type.cpp"
```

Output:

```json
--8<-- "examples/operator_array__object_t_key_type.output"
```

??? example "Example: (2) access specified object element (const)"

The example below shows how object elements can be read using the `[]` operator.

```cpp
--8<-- "examples/operator_array__object_t_key_type_const.cpp"
```

Output:

```json
--8<-- "examples/operator_array__object_t_key_type_const.output"
```

??? example "Example: (3) access specified object element using string_view"

The example below shows how object elements can be read using the `[]` operator.

```cpp
--8<-- "examples/operator_array__keytype.c++17.cpp"
```

Output:

```json
--8<-- "examples/operator_array__keytype.c++17.output"
```

??? example "Example: (3) access specified object element using string_view (const)"

The example below shows how object elements can be read using the `[]` operator.

```cpp
--8<-- "examples/operator_array__keytype_const.c++17.cpp"
```

Output:

```json
--8<-- "examples/operator_array__keytype_const.c++17.output"
```

??? example "Example: (4) access specified element via JSON Pointer"

The example below shows how values can be read and written using JSON Pointers.

```cpp
--8<-- "examples/operator_array__json_pointer.cpp"
```

Output:

```json
--8<-- "examples/operator_array__json_pointer.output"
```

??? example "Example: (4) access specified element via JSON Pointer (const)"

The example below shows how values can be read using JSON Pointers.

```cpp
--8<-- "examples/operator_array__json_pointer_const.cpp"
```

Output:

```json
--8<-- "examples/operator_array__json_pointer_const.output"
```

See also

  • documentation on unchecked access
  • documentation on runtime assertions
  • see at for access by reference with range checking
  • see value for access with default value
  • basic_json_view::operator[] - the same access on a zero-copy view (a duplicate key resolves to the first member, whereas parse() keeps the last; a missing key gives a discarded view instead of undefined behavior)

Version history

  1. Added in version 1.0.0. Fixed in version 3.13.0 to throw #!cpp std::length_error instead of emptying the array and accessing it out of bounds when idx equals the maximum value of size_type. A missing index in the const version is guarded by a runtime assertion since version 3.13.0.
  2. Added in version 1.0.0. Added overloads for T* key in version 1.1.0. The T* key overloads forward to overload 3 since version 3.11.0.
  3. Added in version 3.11.0. Support for keys convertible to std::string_view added in version 3.13.0, consistently across the lookup functions.
  4. Added in version 2.0.0. A missing array index in the const version is guarded by a runtime assertion since version 3.13.0. Throws parse_error.109 instead of out_of_range.404 for a one-character array index that is not a digit (e.g., /x) in version 3.13.0, as it already did for longer ones.