Skip to content

Commit

Permalink
Rework basic_json element access to accept more key types
Browse files Browse the repository at this point in the history
Rework basic_json element access member functions and operators to
accept any type that meets the requirements defined by type trait
detail::is_usable_as_key_type.

Member functions and operators:
* at()
* operator[]
* value()
* erase()
* find()
* count()
* contains()

Update documentation to reflect these changes.

Add unit tests to excercise the new functions using std::string_view.

Co-authored-by: Niels Lohmann <niels.lohmann@gmail.com>
  • Loading branch information
falbrechtskirchinger and nlohmann committed Apr 25, 2022
1 parent 0d79039 commit 4e60bce
Show file tree
Hide file tree
Showing 17 changed files with 1,214 additions and 247 deletions.
41 changes: 30 additions & 11 deletions doc/mkdocs/docs/api/basic_json/at.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,28 @@ reference at(const typename object_t::key_type& key);
const_reference at(const typename object_t::key_type& key) const;

// (3)
template<typename KeyType>
reference at(KeyType&& key);
template<typename KeyType>
const_reference at(KeyType&& key) const;

// (4)
reference at(const json_pointer& ptr);
const_reference at(const json_pointer& ptr) const;
```
1. Returns a reference to the array element at specified location `idx`, with bounds checking.
2. Returns a reference to the object element at with specified key `key`, with bounds checking.
3. Returns a reference to the element at with specified JSON pointer `ptr`, with bounds checking.
2. Returns a reference to the object element with specified key `key`, with bounds checking.
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 at specified JSON pointer `ptr`, with bounds checking.
## Template parameters
`KeyType`
: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with
[`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md).
This can also be a string view (C++17).
## Parameters
Expand All @@ -25,15 +40,16 @@ const_reference at(const json_pointer& ptr) const;
`key` (in)
: object key of the elements to access
`ptr` (in)
: JSON pointer to the desired element
## Return value
1. reference to the element at index `idx`
2. reference to the element at key `key`
3. reference to the element pointed to by `ptr`
3. reference to the element at key `key`
4. reference to the element pointed to by `ptr`
## Exception safety
Expand All @@ -51,7 +67,8 @@ Strong exception safety: if an exception occurs, the original value stays intact
in this case, calling `at` with a key makes no sense. See example below.
- Throws [`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403) if the key `key` is not
stored in the object; that is, `find(key) == end()`. See example below.
3. The function can throw the following exceptions:
3. See 2.
4. The function can throw the following exceptions:
- Throws [`parse_error.106`](../../home/exceptions.md#jsonexceptionparse_error106) if an array index in the passed
JSON pointer `ptr` begins with '0'. See example below.
- Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if an array index in the passed
Expand All @@ -68,9 +85,10 @@ Strong exception safety: if an exception occurs, the original value stays intact
## Complexity
1. Constant
1. Constant.
2. Logarithmic in the size of the container.
3. Constant
3. Logarithmic in the size of the container.
4. Logarithmic in the size of the container.
## Examples
Expand Down Expand Up @@ -134,7 +152,7 @@ Strong exception safety: if an exception occurs, the original value stays intact
--8<-- "examples/at__object_t_key_type_const.output"
```

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

The example below shows how object elements can be read and written using `at()`. It also demonstrates the different
exceptions that can be thrown.
Expand All @@ -149,7 +167,7 @@ Strong exception safety: if an exception occurs, the original value stays intact
--8<-- "examples/at_json_pointer.output"
```

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

The example below shows how object elements can be read using `at()`. It also demonstrates the different exceptions
that can be thrown.
Expand All @@ -173,4 +191,5 @@ Strong exception safety: if an exception occurs, the original value stays intact

1. Added in version 1.0.0.
2. Added in version 1.0.0.
3. Added in version 2.0.0.
3. Added in version 3.11.0.
4. Added in version 2.0.0.
10 changes: 5 additions & 5 deletions doc/mkdocs/docs/api/basic_json/basic_json.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,16 +201,16 @@ basic_json(basic_json&& other) noexcept;
## Exceptions
1. /
1. (none)
2. The function does not throw exceptions.
3. /
4. /
3. (none)
4. (none)
5. The function can throw the following exceptions:
- Throws [`type_error.301`](../../home/exceptions.md#jsonexceptiontype_error301) if `type_deduction` is
`#!cpp false`, `manual_type` is `value_t::object`, but `init` contains an element which is not a pair whose first
element is a string. In this case, the constructor could not create an object. If `type_deduction` would have been
`#!cpp true`, an array would have been created. See `object(initializer_list_t)` for an example.
6. /
6. (none)
7. The function can throw the following exceptions:
- Throws [`invalid_iterator.201`](../../home/exceptions.md#jsonexceptioninvalid_iterator201) if iterators `first`
and `last` are not compatible (i.e., do not belong to the same JSON value). In this case, the range
Expand All @@ -220,7 +220,7 @@ basic_json(basic_json&& other) noexcept;
element anymore. In this case, the range `[first, last)` is undefined. See example code below.
- Throws [`invalid_iterator.206`](../../home/exceptions.md#jsonexceptioninvalid_iterator206) if iterators `first`
and `last` belong to a `#!json null` value. In this case, the range `[first, last)` is undefined.
8. /
8. (none)
9. The function does not throw exceptions.
## Complexity
Expand Down
32 changes: 21 additions & 11 deletions doc/mkdocs/docs/api/basic_json/contains.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,28 @@

```cpp
// (1)
template<typename KeyT>
bool contains(KeyT && key) const;
bool contains(const typename object_t::key_type& key) const;

// (2)
template<typename KeyType>
bool contains(KeyType&& key) const;

// (3)
bool contains(const json_pointer& ptr) const;
```
1. Check whether an element exists in a JSON object with key equivalent to `key`. If the element is not found or the
1. Check whether an element exists in a JSON object with a key equivalent to `key`. If the element is not found or the
JSON value is not an object, `#!cpp false` is returned.
2. Check whether the given JSON pointer `ptr` can be resolved in the current JSON value.
2. See 1. 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.
3. Check whether the given JSON pointer `ptr` can be resolved in the current JSON value.
## Template parameters
`KeyT`
: A type for an object key other than `basic_json::json_pointer`.
`KeyType`
: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with
[`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md).
This can also be a string view (C++17).
## Parameters
Expand All @@ -30,7 +37,8 @@ bool contains(const json_pointer& ptr) const;
1. `#!cpp true` if an element with specified `key` exists. If no such element with such key is found or the JSON value
is not an object, `#!cpp false` is returned.
2. `#!cpp true` if the JSON pointer can be resolved to a stored value, `#!cpp false` otherwise.
2. See 1.
3. `#!cpp true` if the JSON pointer can be resolved to a stored value, `#!cpp false` otherwise.
## Exception safety
Expand All @@ -39,7 +47,8 @@ Strong exception safety: if an exception occurs, the original value stays intact
## Exceptions
1. The function does not throw exceptions.
2. The function can throw the following exceptions:
2. The function does not throw exceptions.
3. The function can throw the following exceptions:
- Throws [`parse_error.106`](../../home/exceptions.md#jsonexceptionparse_error106) if an array index begins with
`0`.
- Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if an array index was not a
Expand Down Expand Up @@ -74,7 +83,7 @@ Logarithmic in the size of the JSON object.
--8<-- "examples/contains.output"
```

??? example "Example (1) check with JSON pointer"
??? example "Example (3) check with JSON pointer"

The example shows how `contains()` is used.

Expand All @@ -90,5 +99,6 @@ Logarithmic in the size of the JSON object.

## Version history

1. Added in version 3.6.0.
2. Added in version 3.7.0.
1. Added in version 3.11.0.
2. Added in version 3.6.0. Extended template `KeyType` to support comparable types in version 3.11.0.
3. Added in version 3.7.0.
23 changes: 16 additions & 7 deletions doc/mkdocs/docs/api/basic_json/count.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
# <small>nlohmann::basic_json::</small>count

```cpp
template<typename KeyT>
size_type count(KeyT&& key) const;
// (1)
size_type count(const typename object_t::key_type& key) const;

// (2)
template<typename KeyType>
size_type count(KeyType&& key) const;
```
Returns the number of elements with key `key`. If `ObjectType` is the default `std::map` type, the return value will
always be `0` (`key` was not found) or `1` (`key` was found).
1. Returns the number of elements with key `key`. If `ObjectType` is the default `std::map` type, the return value will
always be `0` (`key` was not found) or `1` (`key` was found).
2. See 1. 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.
## Template parameters
`KeyT`
: A type for an object key.
`KeyType`
: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with
[`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md).
This can also be a string view (C++17).
## Parameters
Expand Down Expand Up @@ -52,4 +60,5 @@ This method always returns `0` when executed on a JSON type that is not an objec

## Version history

- Added in version 1.0.0.
1. Added in version 3.11.0.
2. Added in version 1.0.0. Changed parameter `key` type to `KeyType&&` in version 3.11.0.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ using default_object_comparator_t = std::less<>; // since C++14

The default comparator used by [`object_t`](object_t.md).

Since C++14 a transparent comparator is used which prevents unnecessary string construction.
Since C++14 a transparent comparator is used which prevents unnecessary string construction
when looking up a key in an object.

The actual comparator used depends on [`object_t`](object_t.md) and can be obtained via
[`object_comparator_t`](object_comparator_t.md).
Expand Down
39 changes: 30 additions & 9 deletions doc/mkdocs/docs/api/basic_json/erase.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ const_iterator erase(const_iterator first, const_iterator last);
size_type erase(const typename object_t::key_type& key);

// (4)
template<typename KeyType>
size_type erase(KeyType&& key);

// (5)
void erase(const size_type idx);
```
Expand All @@ -29,7 +33,17 @@ void erase(const size_type idx);
3. Removes an element from a JSON object by key.
4. Removes an element from a JSON array by index.
4. See 3. 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.
5. Removes an element from a JSON array by index.
## Template parameters
`KeyType`
: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with
[`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md).
This can also be a string view (C++17).
## Parameters
Expand All @@ -56,7 +70,8 @@ void erase(const size_type idx);
is returned.
3. Number of elements removed. If `ObjectType` is the default `std::map` type, the return value will always be `0`
(`key` was not found) or `1` (`key` was found).
4. /
4. See 3.
5. (none)
## Exception safety
Expand All @@ -83,7 +98,8 @@ Strong exception safety: if an exception occurs, the original value stays intact
3. The function can throw the following exceptions:
- Throws [`type_error.307`](../../home/exceptions.md#jsonexceptiontype_error307) when called on a type other than
JSON object; example: `"cannot use erase() with null"`
4. The function can throw the following exceptions:
4. See 3.
5. The function can throw the following exceptions:
- Throws [`type_error.307`](../../home/exceptions.md#jsonexceptiontype_error307) when called on a type other than
JSON object; example: `"cannot use erase() with null"`
- Throws [`out_of_range.401`](../../home/exceptions.md#jsonexceptionout_of_range401) when `idx >= size()`; example:
Expand All @@ -103,14 +119,16 @@ Strong exception safety: if an exception occurs, the original value stays intact
- strings and binary: linear in the length of the member
- other types: constant
3. `log(size()) + count(key)`
4. Linear in distance between `idx` and the end of the container.
4. `log(size()) + count(key)`
5. Linear in distance between `idx` and the end of the container.
## Notes
1. Invalidates iterators and references at or after the point of the `erase`, including the `end()` iterator.
2. /
2. (none)
3. References and iterators to the erased elements are invalidated. Other references and iterators are not affected.
4. /
4. See 3.
5. (none)
## Examples
Expand Down Expand Up @@ -156,7 +174,7 @@ Strong exception safety: if an exception occurs, the original value stays intact
--8<-- "examples/erase__key_type.output"
```

??? example "Example: (4) remove element from a JSON array given an index"
??? example "Example: (5) remove element from a JSON array given an index"

The example shows the effect of `erase()` using an array index.

Expand All @@ -172,5 +190,8 @@ Strong exception safety: if an exception occurs, the original value stays intact

## Version history

- Added in version 1.0.0.
- Added support for binary types in version 3.8.0.
1. Added in version 1.0.0. Added support for binary types in version 3.8.0.
2. Added in version 1.0.0. Added support for binary types in version 3.8.0.
3. Added in version 1.0.0.
4. Added in version 3.11.0.
5. Added in version 1.0.0.
33 changes: 21 additions & 12 deletions doc/mkdocs/docs/api/basic_json/find.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
# <small>nlohmann::basic_json::</small>find

```cpp
template<typename KeyT>
iterator find(KeyT&& key);

template<typename KeyT>
const_iterator find(KeyT&& key) const;
// (1)
iterator find(const typename object_t::key_type& key);
const_iterator find(const typename object_t::key_type& key) const;

// (2)
template<typename KeyType>
iterator find(KeyType&& key);
template<typename KeyType>
const_iterator find(KeyType&& key) const;
```
Finds an element in a JSON object with key equivalent to `key`. If the element is not found or the JSON value is not an
object, `end()` is returned.
1. Finds an element in a JSON object with a key equivalent to `key`. If the element is not found or the
JSON value is not an object, `end()` is returned.
2. See 1. 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.
## Template parameters
`KeyT`
: A type for an object key.
`KeyType`
: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with
[`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md).
This can also be a string view (C++17).
## Parameters
Expand All @@ -23,8 +31,8 @@ object, `end()` is returned.
## Return value
Iterator to an element with key equivalent to `key`. If no such element is found or the JSON value is not an object,
past-the-end (see `end()`) iterator is returned.
Iterator to an element with a key equivalent to `key`. If no such element is found or the JSON value is not an object,
a past-the-end iterator (see `end()`) is returned.
## Exception safety
Expand Down Expand Up @@ -60,4 +68,5 @@ This method always returns `end()` when executed on a JSON type that is not an o

## Version history

- Added in version 1.0.0.
1. Added in version 3.11.0.
2. Added in version 1.0.0. Changed to support comparable types in version 3.11.0.
Loading

0 comments on commit 4e60bce

Please sign in to comment.