mirror of
https://github.com/nlohmann/json.git
synced 2024-11-27 16:49:02 +08:00
Implement support for string_view (attempt no. 3) (#3423)
* Add key_compare member to ordered_map * Replace == with key_compare in ordered_map * Expose the actual comparison function used by object_t nlohmann::ordered_map uses a different comparison function than the one provided via template parameter. * Introduce a type trait to detect if object_t has a key_compare member. * Rename object_comparator_t to default_object_comparator_t. * Add object_comparator_t to be conditionally defined as object_t::key_compare, if available, or default_object_comparator_t otherwise. * Update the documentation accordingly. Co-authored-by: Niels Lohmann <niels.lohmann@gmail.com> * Add type traits to check if a type is usable as object key Add type trait to check: * if a type is a specialization of a template. * if a type is a json_pointer. * if a type is a basic_json::{const_,}iterator. * if two types are comparable using a given comparison functor. * if a type is comparable to basic_json::object_t::key_type. * if a type has a member type is_transparent. * if a type is usable as object key. * if a type has an erase() function accepting a given KeyType. Co-authored-by: Niels Lohmann <niels.lohmann@gmail.com> * Rework basic_json element access to accept more key types 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> Co-authored-by: Niels Lohmann <niels.lohmann@gmail.com>
This commit is contained in:
parent
ee51661481
commit
5352856f04
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
@ -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.
|
||||
@ -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.
|
||||
|
@ -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
|
||||
@ -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
|
||||
|
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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.
|
||||
|
||||
@ -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.
|
||||
|
@ -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
|
||||
|
||||
@ -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.
|
||||
|
@ -0,0 +1,19 @@
|
||||
# <small>nlohmann::basic_json::</small>default_object_comparator_t
|
||||
|
||||
```cpp
|
||||
using default_object_comparator_t = std::less<StringType>; // until C++14
|
||||
|
||||
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
|
||||
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).
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.11.0.
|
@ -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);
|
||||
```
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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:
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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.
|
||||
|
@ -1,20 +1,28 @@
|
||||
# <small>nlohmann::basic_json::</small>find
|
||||
|
||||
```cpp
|
||||
template<typename KeyT>
|
||||
iterator find(KeyT&& key);
|
||||
// (1)
|
||||
iterator find(const typename object_t::key_type& key);
|
||||
const_iterator find(const typename object_t::key_type& key) const;
|
||||
|
||||
template<typename KeyT>
|
||||
const_iterator find(KeyT&& 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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
@ -128,6 +128,7 @@ The class satisfies the following concept requirements:
|
||||
- [**array_t**](array_t.md) - type for arrays
|
||||
- [**binary_t**](binary_t.md) - type for binary arrays
|
||||
- [**boolean_t**](boolean_t.md) - type for booleans
|
||||
- [**default_object_comparator_t**](default_object_comparator_t.md) - default comparator for objects
|
||||
- [**number_float_t**](number_float_t.md) - type for numbers (floating-point)
|
||||
- [**number_integer_t**](number_integer_t.md) - type for numbers (integer)
|
||||
- [**number_unsigned_t**](number_unsigned_t.md) - type for numbers (unsigned)
|
||||
|
@ -50,7 +50,7 @@ void insert(const_iterator first, const_iterator last);
|
||||
2. iterator pointing to the first element inserted, or `pos` if `#!cpp cnt==0`
|
||||
3. iterator pointing to the first element inserted, or `pos` if `#!cpp first==last`
|
||||
4. iterator pointing to the first element inserted, or `pos` if `ilist` is empty
|
||||
5. /
|
||||
5. (none)
|
||||
|
||||
## Exception safety
|
||||
|
||||
|
@ -1,16 +1,16 @@
|
||||
# <small>nlohmann::basic_json::</small>object_comparator_t
|
||||
|
||||
```cpp
|
||||
using object_comparator_t = std::less<StringType>; // until C++14
|
||||
|
||||
using object_comparator_t = std::less<>; // since C++14
|
||||
```cpp
|
||||
using object_comparator_t = typename object_t::key_compare;
|
||||
// or
|
||||
using object_comparator_t = default_object_comparator_t;
|
||||
```
|
||||
|
||||
The comparator used in [`object_t`](object_t.md).
|
||||
|
||||
When C++14 is detected, a transparent comparator is used which, when combined with perfect forwarding on find() and
|
||||
count() calls, prevents unnecessary string construction.
|
||||
The comparator used by [`object_t`](object_t.md). Defined as `#!cpp typename object_t::key_compare` if available,
|
||||
and [`default_object_comparator_t`](default_object_comparator_t.md) otherwise.
|
||||
|
||||
## Version history
|
||||
|
||||
- Unknown.
|
||||
- Added in version 3.0.0.
|
||||
- Changed to be conditionally defined as `#!cpp typename object_t::key_compare` or `default_object_comparator_t` in version 3.11.0.
|
||||
|
@ -3,7 +3,7 @@
|
||||
```cpp
|
||||
using object_t = ObjectType<StringType,
|
||||
basic_json,
|
||||
object_comparator_t,
|
||||
default_object_comparator_t,
|
||||
AllocatorType<std::pair<const StringType, basic_json>>>;
|
||||
```
|
||||
|
||||
@ -52,7 +52,7 @@ std::map<
|
||||
>
|
||||
```
|
||||
|
||||
See [`object_comparator_t`](object_comparator_t.md) for more information.
|
||||
See [`default_object_comparator_t`](default_object_comparator_t.md) for more information.
|
||||
|
||||
#### Behavior
|
||||
|
||||
|
@ -6,26 +6,32 @@ reference operator[](size_type idx);
|
||||
const_reference operator[](size_type idx) const;
|
||||
|
||||
// (2)
|
||||
reference operator[](const typename object_t::key_type& key);
|
||||
reference operator[](typename object_t::key_type key);
|
||||
const_reference operator[](const typename object_t::key_type& key) const;
|
||||
template<typename T>
|
||||
reference operator[](T* key);
|
||||
template<typename T>
|
||||
const_reference operator[](T* 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 at with specified key `key`.
|
||||
3. Returns a reference to the element at with specified JSON pointer `ptr`.
|
||||
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
|
||||
|
||||
`T`
|
||||
: string literal convertible to `object_t::key_type`
|
||||
`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
|
||||
|
||||
@ -40,9 +46,10 @@ const_reference operator[](const json_pointer& ptr) const;
|
||||
|
||||
## 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`
|
||||
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
|
||||
|
||||
@ -56,7 +63,8 @@ Strong exception safety: if an exception occurs, the original value stays intact
|
||||
2. The function can throw the following exceptions:
|
||||
- Throws [`type_error.305`](../../home/exceptions.md#jsonexceptiontype_error305) if the JSON value is not an object
|
||||
or null; in that case, using the `[]` operator with a key makes no sense.
|
||||
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'.
|
||||
- Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if an array index in the passed
|
||||
@ -70,7 +78,8 @@ Strong exception safety: if an exception occurs, the original value stays intact
|
||||
|
||||
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. Constant
|
||||
3. Logarithmic in the size of the container.
|
||||
4. Logarithmic in the size of the container.
|
||||
|
||||
## Notes
|
||||
|
||||
@ -87,7 +96,9 @@ Strong exception safety: if an exception occurs, the original value stays intact
|
||||
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. `null` values are created in arrays and objects if necessary.
|
||||
3. See 2.
|
||||
|
||||
4. `null` values are created in arrays and objects if necessary.
|
||||
|
||||
In particular:
|
||||
|
||||
@ -143,7 +154,7 @@ Strong exception safety: if an exception occurs, the original value stays intact
|
||||
--8<-- "examples/operatorarray__key_type.output"
|
||||
```
|
||||
|
||||
??? example "Example (2): access specified object element"
|
||||
??? example "Example (2): access specified object element (const)"
|
||||
|
||||
The example below shows how object elements can be read using the `[]` operator.
|
||||
|
||||
@ -157,7 +168,7 @@ Strong exception safety: if an exception occurs, the original value stays intact
|
||||
--8<-- "examples/operatorarray__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 values can be read and written using JSON Pointers.
|
||||
|
||||
@ -171,7 +182,7 @@ Strong exception safety: if an exception occurs, the original value stays intact
|
||||
--8<-- "examples/operatorjson_pointer.output"
|
||||
```
|
||||
|
||||
??? example "Example (3): access specified element via JSON Pointer"
|
||||
??? example "Example (4): access specified element via JSON Pointer (const)"
|
||||
|
||||
The example below shows how values can be read using JSON Pointers.
|
||||
|
||||
@ -193,5 +204,6 @@ Strong exception safety: if an exception occurs, the original value stays intact
|
||||
## Version history
|
||||
|
||||
1. Added in version 1.0.0.
|
||||
2. Added in version 1.0.0. Overloads for `T* key` added in version 1.1.0.
|
||||
3. Added in version 2.0.0.
|
||||
2. Added in version 1.0.0. Added overloads for `T* key` in version 1.1.0. Removed overloads for `T* key` (replaced by 3) in version 3.11.0.
|
||||
3. Added in version 3.11.0.
|
||||
4. Added in version 2.0.0.
|
||||
|
@ -28,7 +28,7 @@ The exact mapping and its limitations is described on a [dedicated page](../../f
|
||||
## Return value
|
||||
|
||||
1. BSON serialization as byte vector
|
||||
2. /
|
||||
2. (none)
|
||||
|
||||
## Exception safety
|
||||
|
||||
|
@ -29,7 +29,7 @@ The exact mapping and its limitations is described on a [dedicated page](../../f
|
||||
## Return value
|
||||
|
||||
1. CBOR serialization as byte vector
|
||||
2. /
|
||||
2. (none)
|
||||
|
||||
## Exception safety
|
||||
|
||||
|
@ -28,7 +28,7 @@ The exact mapping and its limitations is described on a [dedicated page](../../f
|
||||
## Return value
|
||||
|
||||
1. MessagePack serialization as byte vector
|
||||
2. /
|
||||
2. (none)
|
||||
|
||||
## Exception safety
|
||||
|
||||
|
@ -39,7 +39,7 @@ The exact mapping and its limitations is described on a [dedicated page](../../f
|
||||
## Return value
|
||||
|
||||
1. UBJSON serialization as byte vector
|
||||
2. /
|
||||
2. (none)
|
||||
|
||||
## Exception safety
|
||||
|
||||
|
@ -4,9 +4,14 @@
|
||||
// (1)
|
||||
template<class ValueType>
|
||||
ValueType value(const typename object_t::key_type& key,
|
||||
const ValueType& default_value) const;
|
||||
ValueType&& default_value) const;
|
||||
|
||||
// (2)
|
||||
template<class KeyType, class ValueType>
|
||||
ValueType value(KeyType&& key,
|
||||
ValueType&& default_value) const;
|
||||
|
||||
// (3)
|
||||
template<class ValueType>
|
||||
ValueType value(const json_pointer& ptr,
|
||||
const ValueType& default_value) const;
|
||||
@ -24,7 +29,10 @@ ValueType value(const json_pointer& ptr,
|
||||
}
|
||||
```
|
||||
|
||||
2. Returns either a copy of an object's element at the specified JSON pointer `ptr` or a given default value if no 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. Returns either a copy of an object's element at the specified JSON pointer `ptr` or a given default value if no value
|
||||
at `ptr` exists.
|
||||
|
||||
The function is basically equivalent to executing
|
||||
@ -44,6 +52,10 @@ ValueType value(const json_pointer& ptr,
|
||||
|
||||
## 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).
|
||||
`ValueType`
|
||||
: type compatible to JSON values, for instance `#!cpp int` for JSON integer numbers, `#!cpp bool` for JSON booleans,
|
||||
or `#!cpp std::vector` types for JSON arrays. Note the type of the expected value at `key`/`ptr` and the default
|
||||
@ -55,7 +67,7 @@ ValueType value(const json_pointer& ptr,
|
||||
: key of the element to access
|
||||
|
||||
`default_value` (in)
|
||||
: the value to return if key/ptr found no value
|
||||
: the value to return if `key`/`ptr` found no value
|
||||
|
||||
`ptr` (in)
|
||||
: a JSON pointer to the element to access
|
||||
@ -63,7 +75,8 @@ ValueType value(const json_pointer& ptr,
|
||||
## Return value
|
||||
|
||||
1. copy of the element at key `key` or `default_value` if `key` is not found
|
||||
1. copy of the element at JSON Pointer `ptr` or `default_value` if no value for `ptr` is found
|
||||
2. copy of the element at key `key` or `default_value` if `key` is not found
|
||||
3. copy of the element at JSON Pointer `ptr` or `default_value` if no value for `ptr` is found
|
||||
|
||||
## Exception safety
|
||||
|
||||
@ -77,7 +90,8 @@ changes to any JSON value.
|
||||
the type of the value at `key`
|
||||
- Throws [`type_error.306`](../../home/exceptions.md#jsonexceptiontype_error306) if the JSON value is not an object;
|
||||
in that case, using `value()` with a key makes no sense.
|
||||
2. The function can throw the following exceptions:
|
||||
2. See 1.
|
||||
3. The function can throw the following exceptions:
|
||||
- Throws [`type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302) if `default_value` does not match
|
||||
the type of the value at `ptr`
|
||||
- Throws [`type_error.306`](../../home/exceptions.md#jsonexceptiontype_error306) if the JSON value is not an object;
|
||||
@ -87,6 +101,7 @@ changes to any JSON value.
|
||||
|
||||
1. Logarithmic in the size of the container.
|
||||
2. Logarithmic in the size of the container.
|
||||
3. Logarithmic in the size of the container.
|
||||
|
||||
## Examples
|
||||
|
||||
@ -104,7 +119,7 @@ changes to any JSON value.
|
||||
--8<-- "examples/basic_json__value.output"
|
||||
```
|
||||
|
||||
??? example "Example (2): access specified object element via JSON Pointer with default value"
|
||||
??? example "Example (3): access specified object element via JSON Pointer with default value"
|
||||
|
||||
The example below shows how object elements can be queried with a default value.
|
||||
|
||||
@ -125,5 +140,6 @@ changes to any JSON value.
|
||||
|
||||
## Version history
|
||||
|
||||
1. Added in version 1.0.0.
|
||||
2. Added in version 2.0.2.
|
||||
1. Added in version 1.0.0. Changed parameter `default_value` type from `const ValueType&` to `ValueType&&` in version 3.11.0.
|
||||
2. Added in version 3.11.0.
|
||||
3. Added in version 2.0.2.
|
||||
|
@ -32,6 +32,12 @@ A minimal map-like container that preserves insertion order for use within [`nlo
|
||||
- **const_iterator**
|
||||
- **size_type**
|
||||
- **value_type**
|
||||
- **key_compare** - key comparison function
|
||||
```cpp
|
||||
std::equal_to<Key> // until C++14
|
||||
|
||||
std::equal_to<> // since C++14
|
||||
```
|
||||
|
||||
## Member functions
|
||||
|
||||
@ -68,3 +74,4 @@ A minimal map-like container that preserves insertion order for use within [`nlo
|
||||
## Version history
|
||||
|
||||
- Added in version 3.9.0 to implement [`nlohmann::ordered_json`](ordered_json.md).
|
||||
- Added **key_compare** member in version 3.11.0.
|
||||
|
@ -97,6 +97,7 @@ nav:
|
||||
- 'count': api/basic_json/count.md
|
||||
- 'crbegin': api/basic_json/crbegin.md
|
||||
- 'crend': api/basic_json/crend.md
|
||||
- 'default_object_comparator_t': api/basic_json/default_object_comparator_t.md
|
||||
- 'diff': api/basic_json/diff.md
|
||||
- 'dump': api/basic_json/dump.md
|
||||
- 'emplace': api/basic_json/emplace.md
|
||||
|
@ -106,6 +106,12 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
|
||||
#define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
|
||||
#else
|
||||
#define JSON_NO_UNIQUE_ADDRESS
|
||||
#endif
|
||||
|
||||
// disable documentation warnings on clang
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
|
@ -14,6 +14,7 @@
|
||||
#undef NLOHMANN_BASIC_JSON_TPL
|
||||
#undef JSON_EXPLICIT
|
||||
#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
|
||||
#undef JSON_NO_UNIQUE_ADDRESS
|
||||
|
||||
#ifndef JSON_TEST_KEEP_MACROS
|
||||
#undef JSON_CATCH
|
||||
|
@ -54,11 +54,6 @@ struct is_basic_json_context :
|
||||
|| std::is_same<BasicJsonContext, std::nullptr_t>::value >
|
||||
{};
|
||||
|
||||
template<typename> struct is_json_pointer : std::false_type {};
|
||||
|
||||
template<typename RefStringType>
|
||||
struct is_json_pointer<json_pointer<RefStringType>> : std::true_type {};
|
||||
|
||||
//////////////////////
|
||||
// json_ref helpers //
|
||||
//////////////////////
|
||||
@ -160,6 +155,24 @@ struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
|
||||
T>::value;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using detect_key_compare = typename T::key_compare;
|
||||
|
||||
template<typename T>
|
||||
struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
|
||||
|
||||
// obtains the actual object key comparator
|
||||
template<typename BasicJsonType>
|
||||
struct actual_object_comparator
|
||||
{
|
||||
using object_t = typename BasicJsonType::object_t;
|
||||
using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
|
||||
using type = typename std::conditional < has_key_compare<object_t>::value,
|
||||
typename object_t::key_compare, object_comparator_t>::type;
|
||||
};
|
||||
|
||||
template<typename BasicJsonType>
|
||||
using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type;
|
||||
|
||||
///////////////////
|
||||
// is_ functions //
|
||||
@ -454,6 +467,78 @@ struct is_constructible_tuple : std::false_type {};
|
||||
template<typename T1, typename... Args>
|
||||
struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
|
||||
|
||||
template<typename BasicJsonType, typename T>
|
||||
struct is_json_iterator_of : std::false_type {};
|
||||
|
||||
template<typename BasicJsonType>
|
||||
struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
|
||||
|
||||
template<typename BasicJsonType>
|
||||
struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
|
||||
{};
|
||||
|
||||
// checks if a given type T is a template specialization of Primary
|
||||
template<template <typename...> class Primary, typename T>
|
||||
struct is_specialization_of : std::false_type {};
|
||||
|
||||
template<template <typename...> class Primary, typename... Args>
|
||||
struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
|
||||
|
||||
template<typename T>
|
||||
using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>;
|
||||
|
||||
// checks if A and B are comparable using Compare functor
|
||||
template<typename Compare, typename A, typename B, typename = void>
|
||||
struct is_comparable : std::false_type {};
|
||||
|
||||
template<typename Compare, typename A, typename B>
|
||||
struct is_comparable<Compare, A, B, void_t<
|
||||
decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
|
||||
decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
|
||||
>> : std::true_type {};
|
||||
|
||||
// checks if BasicJsonType::object_t::key_type and KeyType are comparable using Compare functor
|
||||
template<typename BasicJsonType, typename KeyType>
|
||||
using is_key_type_comparable = typename is_comparable <
|
||||
typename BasicJsonType::object_comparator_t,
|
||||
const key_type_t<typename BasicJsonType::object_t>&,
|
||||
KeyType >::type;
|
||||
|
||||
template<typename T>
|
||||
using detect_is_transparent = typename T::is_transparent;
|
||||
|
||||
// type trait to check if KeyType can be used as object key
|
||||
// true if:
|
||||
// - KeyType is comparable with BasicJsonType::object_t::key_type
|
||||
// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
|
||||
// - the comparator is transparent or RequireTransparentComparator is false
|
||||
// - KeyType is not a JSON iterator or json_pointer
|
||||
template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
|
||||
bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
|
||||
using is_usable_as_key_type = typename std::conditional <
|
||||
is_key_type_comparable<BasicJsonType, KeyTypeCVRef>::value
|
||||
&& !(ExcludeObjectKeyType && std::is_same<KeyType,
|
||||
typename BasicJsonType::object_t::key_type>::value)
|
||||
&& (!RequireTransparentComparator || is_detected <
|
||||
detect_is_transparent,
|
||||
typename BasicJsonType::object_comparator_t >::value)
|
||||
&& !is_json_iterator_of<BasicJsonType, KeyType>::value
|
||||
&& !is_json_pointer<KeyType>::value,
|
||||
std::true_type,
|
||||
std::false_type >::type;
|
||||
|
||||
template<typename ObjectType, typename KeyType>
|
||||
using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
|
||||
|
||||
// type trait to check if object_t has an erase() member functions accepting KeyType
|
||||
template<typename BasicJsonType, typename KeyType>
|
||||
using has_erase_with_key_type = typename std::conditional <
|
||||
is_detected <
|
||||
detect_erase_with_key_type,
|
||||
typename BasicJsonType::object_t, KeyType >::value,
|
||||
std::true_type,
|
||||
std::false_type >::type;
|
||||
|
||||
// a naive helper to check if a type is an ordered_map (exploits the fact that
|
||||
// ordered_map inherits capacity() from std::vector)
|
||||
template <typename T>
|
||||
|
@ -350,21 +350,23 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// the template arguments passed to class @ref basic_json.
|
||||
/// @{
|
||||
|
||||
/// @brief object key comparator type
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
|
||||
/// @brief default object key comparator type
|
||||
/// The actual object key comparator type (@ref object_comparator_t) may be
|
||||
/// different.
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/
|
||||
#if defined(JSON_HAS_CPP_14)
|
||||
// Use transparent comparator if possible, combined with perfect forwarding
|
||||
// on find() and count() calls prevents unnecessary string construction.
|
||||
using object_comparator_t = std::less<>;
|
||||
// use of transparent comparator avoids unnecessary repeated construction of temporaries
|
||||
// in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
|
||||
using default_object_comparator_t = std::less<>;
|
||||
#else
|
||||
using object_comparator_t = std::less<StringType>;
|
||||
using default_object_comparator_t = std::less<StringType>;
|
||||
#endif
|
||||
|
||||
/// @brief a type for an object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/object_t/
|
||||
using object_t = ObjectType<StringType,
|
||||
basic_json,
|
||||
object_comparator_t,
|
||||
default_object_comparator_t,
|
||||
AllocatorType<std::pair<const StringType,
|
||||
basic_json>>>;
|
||||
|
||||
@ -396,6 +398,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/binary_t/
|
||||
using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
|
||||
|
||||
/// @brief object key comparator type
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
|
||||
using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
|
||||
|
||||
/// @}
|
||||
|
||||
private:
|
||||
@ -2000,22 +2006,37 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
reference at(const typename object_t::key_type& key)
|
||||
{
|
||||
// at only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
JSON_TRY
|
||||
{
|
||||
return set_parent(m_value.object->at(key));
|
||||
}
|
||||
JSON_CATCH (std::out_of_range&)
|
||||
{
|
||||
// create better exception explanation
|
||||
JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
|
||||
}
|
||||
}
|
||||
else
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
|
||||
}
|
||||
|
||||
auto it = m_value.object->find(key);
|
||||
if (it == m_value.object->end())
|
||||
{
|
||||
JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
|
||||
}
|
||||
return set_parent(it->second);
|
||||
}
|
||||
|
||||
/// @brief access specified object element with bounds checking
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/at/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
reference at(KeyType && key)
|
||||
{
|
||||
// at only works for objects
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
|
||||
}
|
||||
|
||||
auto it = m_value.object->find(std::forward<KeyType>(key));
|
||||
if (it == m_value.object->end())
|
||||
{
|
||||
JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
|
||||
}
|
||||
return set_parent(it->second);
|
||||
}
|
||||
|
||||
/// @brief access specified object element with bounds checking
|
||||
@ -2023,22 +2044,37 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
const_reference at(const typename object_t::key_type& key) const
|
||||
{
|
||||
// at only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
JSON_TRY
|
||||
{
|
||||
return m_value.object->at(key);
|
||||
}
|
||||
JSON_CATCH (std::out_of_range&)
|
||||
{
|
||||
// create better exception explanation
|
||||
JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
|
||||
}
|
||||
}
|
||||
else
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
|
||||
}
|
||||
|
||||
auto it = m_value.object->find(key);
|
||||
if (it == m_value.object->end())
|
||||
{
|
||||
JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
/// @brief access specified object element with bounds checking
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/at/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
const_reference at(KeyType && key) const
|
||||
{
|
||||
// at only works for objects
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
|
||||
}
|
||||
|
||||
auto it = m_value.object->find(std::forward<KeyType>(key));
|
||||
if (it == m_value.object->end())
|
||||
{
|
||||
JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
/// @brief access specified array element
|
||||
@ -2102,7 +2138,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// @brief access specified object element
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
|
||||
reference operator[](const typename object_t::key_type& key)
|
||||
reference operator[](typename object_t::key_type key)
|
||||
{
|
||||
// implicitly convert null value to an empty object
|
||||
if (is_null())
|
||||
@ -2115,7 +2151,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
// operator[] only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
return set_parent(m_value.object->operator[](key));
|
||||
auto result = m_value.object->emplace(std::move(key), nullptr);
|
||||
return set_parent(result.first->second);
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
|
||||
@ -2128,31 +2165,47 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
// const operator[] only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
|
||||
return m_value.object->find(key)->second;
|
||||
auto it = m_value.object->find(key);
|
||||
JSON_ASSERT(it != m_value.object->end());
|
||||
return it->second;
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
|
||||
}
|
||||
|
||||
/// @brief access specified object element
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
|
||||
// these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
|
||||
// (they seemingly cannot be constrained to resolve the ambiguity)
|
||||
template<typename T>
|
||||
JSON_HEDLEY_NON_NULL(2)
|
||||
reference operator[](T* key)
|
||||
{
|
||||
// implicitly convert null to object
|
||||
return operator[](typename object_t::key_type(key));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const_reference operator[](T* key) const
|
||||
{
|
||||
return operator[](typename object_t::key_type(key));
|
||||
}
|
||||
|
||||
/// @brief access specified object element
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
reference operator[](KeyType && key)
|
||||
{
|
||||
// implicitly convert null value to an empty object
|
||||
if (is_null())
|
||||
{
|
||||
m_type = value_t::object;
|
||||
m_value = value_t::object;
|
||||
m_value.object = create<object_t>();
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
// at only works for objects
|
||||
// operator[] only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
return set_parent(m_value.object->operator[](key));
|
||||
auto result = m_value.object->emplace(std::forward<KeyType>(key), nullptr);
|
||||
return set_parent(result.first->second);
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
|
||||
@ -2160,15 +2213,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// @brief access specified object element
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
|
||||
template<typename T>
|
||||
JSON_HEDLEY_NON_NULL(2)
|
||||
const_reference operator[](T* key) const
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
const_reference operator[](KeyType && key) const
|
||||
{
|
||||
// at only works for objects
|
||||
// const operator[] only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
|
||||
return m_value.object->find(key)->second;
|
||||
auto it = m_value.object->find(std::forward<KeyType>(key));
|
||||
JSON_ASSERT(it != m_value.object->end());
|
||||
return it->second;
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
|
||||
@ -2176,23 +2230,24 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// @brief access specified object element with default value
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||
/// using std::is_convertible in a std::enable_if will fail when using explicit conversions
|
||||
template < class ValueType, typename std::enable_if <
|
||||
detail::is_getable<basic_json_t, ValueType>::value
|
||||
&& !std::is_same<value_t, ValueType>::value, int >::type = 0 >
|
||||
ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
|
||||
// this is the value(const typename object_t::key_type&) overload
|
||||
template < class KeyType, class ValueType, detail::enable_if_t <
|
||||
std::is_same<KeyType, typename object_t::key_type>::value
|
||||
&& detail::is_getable<basic_json_t, ValueType>::value
|
||||
&& !std::is_same<value_t, ValueType>::value, int > = 0 >
|
||||
typename std::decay<ValueType>::type value(const KeyType& key, ValueType && default_value) const
|
||||
{
|
||||
// at only works for objects
|
||||
// value only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
// if key is found, return value and given default value otherwise
|
||||
const auto it = find(key);
|
||||
if (it != end())
|
||||
{
|
||||
return it->template get<ValueType>();
|
||||
return it->template get<typename std::decay<ValueType>::type>();
|
||||
}
|
||||
|
||||
return default_value;
|
||||
return std::forward<ValueType>(default_value);
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
@ -2206,13 +2261,64 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
return value(key, string_t(default_value));
|
||||
}
|
||||
|
||||
// these two functions, in conjunction with value(const KeyType &, ValueType &&),
|
||||
// resolve an ambiguity that would otherwise occur between the json_pointer and
|
||||
// typename object_t::key_type & overloads
|
||||
template < class ValueType, detail::enable_if_t <
|
||||
detail::is_getable<basic_json_t, ValueType>::value
|
||||
&& !std::is_same<value_t, ValueType>::value, int > = 0 >
|
||||
typename std::decay<ValueType>::type value(const char* key, ValueType && default_value) const
|
||||
{
|
||||
return value(typename object_t::key_type(key), std::forward<ValueType>(default_value));
|
||||
}
|
||||
|
||||
string_t value(const char* key, const char* default_value) const
|
||||
{
|
||||
return value(typename object_t::key_type(key), string_t(default_value));
|
||||
}
|
||||
|
||||
/// @brief access specified object element with default value
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||
/// using std::is_convertible in a std::enable_if will fail when using explicit conversions
|
||||
template < class KeyType, class ValueType, detail::enable_if_t <
|
||||
detail::is_getable<basic_json_t, ValueType>::value
|
||||
&& !std::is_same<value_t, ValueType>::value
|
||||
&& detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
typename std::decay<ValueType>::type value(KeyType && key, ValueType && default_value) const
|
||||
{
|
||||
// value only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
// if key is found, return value and given default value otherwise
|
||||
const auto it = find(std::forward<KeyType>(key));
|
||||
if (it != end())
|
||||
{
|
||||
return it->template get<typename std::decay<ValueType>::type>();
|
||||
}
|
||||
|
||||
return std::forward<ValueType>(default_value);
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
}
|
||||
|
||||
/// @brief access specified object element with default value
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||
/// overload for a default value of type const char*
|
||||
template < class KeyType, detail::enable_if_t <
|
||||
!detail::is_json_pointer<KeyType>::value, int > = 0 >
|
||||
string_t value(KeyType && key, const char* default_value) const
|
||||
{
|
||||
return value(std::forward<KeyType>(key), string_t(default_value));
|
||||
}
|
||||
|
||||
/// @brief access specified object element via JSON Pointer with default value
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||
template<class ValueType, typename std::enable_if<
|
||||
detail::is_getable<basic_json_t, ValueType>::value, int>::type = 0>
|
||||
template < class ValueType, detail::enable_if_t <
|
||||
detail::is_getable<basic_json_t, ValueType>::value, int> = 0 >
|
||||
ValueType value(const json_pointer& ptr, const ValueType& default_value) const
|
||||
{
|
||||
// at only works for objects
|
||||
// value only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
// if pointer resolves a value, return it or use default value
|
||||
@ -2229,8 +2335,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
}
|
||||
|
||||
template<class ValueType, class BasicJsonType, typename std::enable_if<
|
||||
detail::is_getable<basic_json_t, ValueType>::value, int>::type = 0>
|
||||
template < class ValueType, class BasicJsonType, detail::enable_if_t <
|
||||
detail::is_getable<basic_json_t, ValueType>::value, int> = 0 >
|
||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
|
||||
ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
|
||||
{
|
||||
@ -2288,10 +2394,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// @brief remove element given an iterator
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/erase/
|
||||
template < class IteratorType, typename std::enable_if <
|
||||
template < class IteratorType, detail::enable_if_t <
|
||||
std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
|
||||
std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
|
||||
= 0 >
|
||||
std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
|
||||
IteratorType erase(IteratorType pos)
|
||||
{
|
||||
// make sure iterator fits the current value
|
||||
@ -2359,10 +2464,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// @brief remove elements given an iterator range
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/erase/
|
||||
template < class IteratorType, typename std::enable_if <
|
||||
template < class IteratorType, detail::enable_if_t <
|
||||
std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
|
||||
std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
|
||||
= 0 >
|
||||
std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
|
||||
IteratorType erase(IteratorType first, IteratorType last)
|
||||
{
|
||||
// make sure iterator fits the current value
|
||||
@ -2431,17 +2535,57 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
template < typename KeyType, detail::enable_if_t <
|
||||
detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
size_type erase_internal(KeyType && key)
|
||||
{
|
||||
// this erase only works for objects
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
|
||||
}
|
||||
|
||||
return m_value.object->erase(std::forward<KeyType>(key));
|
||||
}
|
||||
|
||||
template < typename KeyType, detail::enable_if_t <
|
||||
!detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
size_type erase_internal(KeyType && key)
|
||||
{
|
||||
// this erase only works for objects
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
|
||||
}
|
||||
|
||||
const auto it = m_value.object->find(std::forward<KeyType>(key));
|
||||
if (it != m_value.object->end())
|
||||
{
|
||||
m_value.object->erase(it);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// @brief remove element from a JSON object given a key
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/erase/
|
||||
size_type erase(const typename object_t::key_type& key)
|
||||
{
|
||||
// this erase only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
return m_value.object->erase(key);
|
||||
}
|
||||
// the indirection via erase_internal() is added to avoid making this
|
||||
// function a template and thus de-rank it during overload resolution
|
||||
return erase_internal(key);
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
|
||||
/// @brief remove element from a JSON object given a key
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/erase/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
size_type erase(KeyType && key)
|
||||
{
|
||||
return erase_internal(std::forward<KeyType>(key));
|
||||
}
|
||||
|
||||
/// @brief remove element from a JSON array given an index
|
||||
@ -2476,14 +2620,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// @brief find an element in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/find/
|
||||
template<typename KeyT>
|
||||
iterator find(KeyT&& key)
|
||||
iterator find(const typename object_t::key_type& key)
|
||||
{
|
||||
auto result = end();
|
||||
|
||||
if (is_object())
|
||||
{
|
||||
result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
|
||||
result.m_it.object_iterator = m_value.object->find(key);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -2491,14 +2634,45 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// @brief find an element in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/find/
|
||||
template<typename KeyT>
|
||||
const_iterator find(KeyT&& key) const
|
||||
const_iterator find(const typename object_t::key_type& key) const
|
||||
{
|
||||
auto result = cend();
|
||||
|
||||
if (is_object())
|
||||
{
|
||||
result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
|
||||
result.m_it.object_iterator = m_value.object->find(key);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// @brief find an element in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/find/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
iterator find(KeyType && key)
|
||||
{
|
||||
auto result = end();
|
||||
|
||||
if (is_object())
|
||||
{
|
||||
result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// @brief find an element in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/find/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
const_iterator find(KeyType && key) const
|
||||
{
|
||||
auto result = cend();
|
||||
|
||||
if (is_object())
|
||||
{
|
||||
result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key));
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -2506,20 +2680,36 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// @brief returns the number of occurrences of a key in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/count/
|
||||
template<typename KeyT>
|
||||
size_type count(KeyT&& key) const
|
||||
size_type count(const typename object_t::key_type& key) const
|
||||
{
|
||||
// return 0 for all nonobject types
|
||||
return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
|
||||
return is_object() ? m_value.object->count(key) : 0;
|
||||
}
|
||||
|
||||
/// @brief returns the number of occurrences of a key in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/count/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
size_type count(KeyType && key) const
|
||||
{
|
||||
// return 0 for all nonobject types
|
||||
return is_object() ? m_value.object->count(std::forward<KeyType>(key)) : 0;
|
||||
}
|
||||
|
||||
/// @brief check the existence of an element in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/contains/
|
||||
template < typename KeyT, typename std::enable_if <
|
||||
!detail::is_json_pointer<typename std::decay<KeyT>::type>::value, int >::type = 0 >
|
||||
bool contains(KeyT && key) const
|
||||
bool contains(const typename object_t::key_type& key) const
|
||||
{
|
||||
return is_object() && m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
|
||||
return is_object() && m_value.object->find(key) != m_value.object->end();
|
||||
}
|
||||
|
||||
/// @brief check the existence of an element in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/contains/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
bool contains(KeyType && key) const
|
||||
{
|
||||
return is_object() && m_value.object->find(std::forward<KeyType>(key)) != m_value.object->end();
|
||||
}
|
||||
|
||||
/// @brief check the existence of an element in a JSON object given a JSON pointer
|
||||
@ -4305,7 +4495,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
return ptr.get_unchecked(this);
|
||||
}
|
||||
|
||||
template<typename BasicJsonType>
|
||||
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
|
||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
|
||||
reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
|
||||
{
|
||||
@ -4319,7 +4509,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
return ptr.get_unchecked(this);
|
||||
}
|
||||
|
||||
template<typename BasicJsonType>
|
||||
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
|
||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
|
||||
const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional> // less
|
||||
#include <functional> // equal_to, less
|
||||
#include <initializer_list> // initializer_list
|
||||
#include <iterator> // input_iterator_tag, iterator_traits
|
||||
#include <memory> // allocator
|
||||
@ -27,6 +27,11 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
using const_iterator = typename Container::const_iterator;
|
||||
using size_type = typename Container::size_type;
|
||||
using value_type = typename Container::value_type;
|
||||
#ifdef JSON_HAS_CPP_14
|
||||
using key_compare = std::equal_to<>;
|
||||
#else
|
||||
using key_compare = std::equal_to<Key>;
|
||||
#endif
|
||||
|
||||
// Explicit constructors instead of `using Container::Container`
|
||||
// otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
|
||||
@ -42,7 +47,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return {it, false};
|
||||
}
|
||||
@ -65,7 +70,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
@ -78,7 +83,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
@ -91,7 +96,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
// Since we cannot move const Keys, re-construct them in place
|
||||
for (auto next = it; ++next != this->end(); ++it)
|
||||
@ -163,7 +168,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -175,7 +180,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return it;
|
||||
}
|
||||
@ -187,7 +192,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return it;
|
||||
}
|
||||
@ -204,7 +209,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == value.first)
|
||||
if (m_compare(it->first, value.first))
|
||||
{
|
||||
return {it, false};
|
||||
}
|
||||
@ -225,6 +230,9 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
insert(*it);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
|
||||
};
|
||||
|
||||
} // namespace nlohmann
|
||||
|
@ -2411,6 +2411,12 @@ using is_detected_convertible =
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
|
||||
#define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
|
||||
#else
|
||||
#define JSON_NO_UNIQUE_ADDRESS
|
||||
#endif
|
||||
|
||||
// disable documentation warnings on clang
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
@ -3183,11 +3189,6 @@ struct is_basic_json_context :
|
||||
|| std::is_same<BasicJsonContext, std::nullptr_t>::value >
|
||||
{};
|
||||
|
||||
template<typename> struct is_json_pointer : std::false_type {};
|
||||
|
||||
template<typename RefStringType>
|
||||
struct is_json_pointer<json_pointer<RefStringType>> : std::true_type {};
|
||||
|
||||
//////////////////////
|
||||
// json_ref helpers //
|
||||
//////////////////////
|
||||
@ -3289,6 +3290,24 @@ struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
|
||||
T>::value;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using detect_key_compare = typename T::key_compare;
|
||||
|
||||
template<typename T>
|
||||
struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
|
||||
|
||||
// obtains the actual object key comparator
|
||||
template<typename BasicJsonType>
|
||||
struct actual_object_comparator
|
||||
{
|
||||
using object_t = typename BasicJsonType::object_t;
|
||||
using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
|
||||
using type = typename std::conditional < has_key_compare<object_t>::value,
|
||||
typename object_t::key_compare, object_comparator_t>::type;
|
||||
};
|
||||
|
||||
template<typename BasicJsonType>
|
||||
using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type;
|
||||
|
||||
///////////////////
|
||||
// is_ functions //
|
||||
@ -3583,6 +3602,78 @@ struct is_constructible_tuple : std::false_type {};
|
||||
template<typename T1, typename... Args>
|
||||
struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
|
||||
|
||||
template<typename BasicJsonType, typename T>
|
||||
struct is_json_iterator_of : std::false_type {};
|
||||
|
||||
template<typename BasicJsonType>
|
||||
struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
|
||||
|
||||
template<typename BasicJsonType>
|
||||
struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
|
||||
{};
|
||||
|
||||
// checks if a given type T is a template specialization of Primary
|
||||
template<template <typename...> class Primary, typename T>
|
||||
struct is_specialization_of : std::false_type {};
|
||||
|
||||
template<template <typename...> class Primary, typename... Args>
|
||||
struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
|
||||
|
||||
template<typename T>
|
||||
using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>;
|
||||
|
||||
// checks if A and B are comparable using Compare functor
|
||||
template<typename Compare, typename A, typename B, typename = void>
|
||||
struct is_comparable : std::false_type {};
|
||||
|
||||
template<typename Compare, typename A, typename B>
|
||||
struct is_comparable<Compare, A, B, void_t<
|
||||
decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
|
||||
decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
|
||||
>> : std::true_type {};
|
||||
|
||||
// checks if BasicJsonType::object_t::key_type and KeyType are comparable using Compare functor
|
||||
template<typename BasicJsonType, typename KeyType>
|
||||
using is_key_type_comparable = typename is_comparable <
|
||||
typename BasicJsonType::object_comparator_t,
|
||||
const key_type_t<typename BasicJsonType::object_t>&,
|
||||
KeyType >::type;
|
||||
|
||||
template<typename T>
|
||||
using detect_is_transparent = typename T::is_transparent;
|
||||
|
||||
// type trait to check if KeyType can be used as object key
|
||||
// true if:
|
||||
// - KeyType is comparable with BasicJsonType::object_t::key_type
|
||||
// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
|
||||
// - the comparator is transparent or RequireTransparentComparator is false
|
||||
// - KeyType is not a JSON iterator or json_pointer
|
||||
template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
|
||||
bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
|
||||
using is_usable_as_key_type = typename std::conditional <
|
||||
is_key_type_comparable<BasicJsonType, KeyTypeCVRef>::value
|
||||
&& !(ExcludeObjectKeyType && std::is_same<KeyType,
|
||||
typename BasicJsonType::object_t::key_type>::value)
|
||||
&& (!RequireTransparentComparator || is_detected <
|
||||
detect_is_transparent,
|
||||
typename BasicJsonType::object_comparator_t >::value)
|
||||
&& !is_json_iterator_of<BasicJsonType, KeyType>::value
|
||||
&& !is_json_pointer<KeyType>::value,
|
||||
std::true_type,
|
||||
std::false_type >::type;
|
||||
|
||||
template<typename ObjectType, typename KeyType>
|
||||
using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
|
||||
|
||||
// type trait to check if object_t has an erase() member functions accepting KeyType
|
||||
template<typename BasicJsonType, typename KeyType>
|
||||
using has_erase_with_key_type = typename std::conditional <
|
||||
is_detected <
|
||||
detect_erase_with_key_type,
|
||||
typename BasicJsonType::object_t, KeyType >::value,
|
||||
std::true_type,
|
||||
std::false_type >::type;
|
||||
|
||||
// a naive helper to check if a type is an ordered_map (exploits the fact that
|
||||
// ordered_map inherits capacity() from std::vector)
|
||||
template <typename T>
|
||||
@ -17834,7 +17925,7 @@ class serializer
|
||||
// #include <nlohmann/ordered_map.hpp>
|
||||
|
||||
|
||||
#include <functional> // less
|
||||
#include <functional> // equal_to, less
|
||||
#include <initializer_list> // initializer_list
|
||||
#include <iterator> // input_iterator_tag, iterator_traits
|
||||
#include <memory> // allocator
|
||||
@ -17862,6 +17953,11 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
using const_iterator = typename Container::const_iterator;
|
||||
using size_type = typename Container::size_type;
|
||||
using value_type = typename Container::value_type;
|
||||
#ifdef JSON_HAS_CPP_14
|
||||
using key_compare = std::equal_to<>;
|
||||
#else
|
||||
using key_compare = std::equal_to<Key>;
|
||||
#endif
|
||||
|
||||
// Explicit constructors instead of `using Container::Container`
|
||||
// otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
|
||||
@ -17877,7 +17973,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return {it, false};
|
||||
}
|
||||
@ -17900,7 +17996,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
@ -17913,7 +18009,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
@ -17926,7 +18022,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
// Since we cannot move const Keys, re-construct them in place
|
||||
for (auto next = it; ++next != this->end(); ++it)
|
||||
@ -17998,7 +18094,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -18010,7 +18106,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return it;
|
||||
}
|
||||
@ -18022,7 +18118,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return it;
|
||||
}
|
||||
@ -18039,7 +18135,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == value.first)
|
||||
if (m_compare(it->first, value.first))
|
||||
{
|
||||
return {it, false};
|
||||
}
|
||||
@ -18060,6 +18156,9 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
insert(*it);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
|
||||
};
|
||||
|
||||
} // namespace nlohmann
|
||||
@ -18321,21 +18420,23 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// the template arguments passed to class @ref basic_json.
|
||||
/// @{
|
||||
|
||||
/// @brief object key comparator type
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
|
||||
/// @brief default object key comparator type
|
||||
/// The actual object key comparator type (@ref object_comparator_t) may be
|
||||
/// different.
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/
|
||||
#if defined(JSON_HAS_CPP_14)
|
||||
// Use transparent comparator if possible, combined with perfect forwarding
|
||||
// on find() and count() calls prevents unnecessary string construction.
|
||||
using object_comparator_t = std::less<>;
|
||||
// use of transparent comparator avoids unnecessary repeated construction of temporaries
|
||||
// in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
|
||||
using default_object_comparator_t = std::less<>;
|
||||
#else
|
||||
using object_comparator_t = std::less<StringType>;
|
||||
using default_object_comparator_t = std::less<StringType>;
|
||||
#endif
|
||||
|
||||
/// @brief a type for an object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/object_t/
|
||||
using object_t = ObjectType<StringType,
|
||||
basic_json,
|
||||
object_comparator_t,
|
||||
default_object_comparator_t,
|
||||
AllocatorType<std::pair<const StringType,
|
||||
basic_json>>>;
|
||||
|
||||
@ -18367,6 +18468,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/binary_t/
|
||||
using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
|
||||
|
||||
/// @brief object key comparator type
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
|
||||
using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
|
||||
|
||||
/// @}
|
||||
|
||||
private:
|
||||
@ -19971,22 +20076,37 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
reference at(const typename object_t::key_type& key)
|
||||
{
|
||||
// at only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
JSON_TRY
|
||||
{
|
||||
return set_parent(m_value.object->at(key));
|
||||
}
|
||||
JSON_CATCH (std::out_of_range&)
|
||||
{
|
||||
// create better exception explanation
|
||||
JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
|
||||
}
|
||||
}
|
||||
else
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
|
||||
}
|
||||
|
||||
auto it = m_value.object->find(key);
|
||||
if (it == m_value.object->end())
|
||||
{
|
||||
JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
|
||||
}
|
||||
return set_parent(it->second);
|
||||
}
|
||||
|
||||
/// @brief access specified object element with bounds checking
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/at/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
reference at(KeyType && key)
|
||||
{
|
||||
// at only works for objects
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
|
||||
}
|
||||
|
||||
auto it = m_value.object->find(std::forward<KeyType>(key));
|
||||
if (it == m_value.object->end())
|
||||
{
|
||||
JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
|
||||
}
|
||||
return set_parent(it->second);
|
||||
}
|
||||
|
||||
/// @brief access specified object element with bounds checking
|
||||
@ -19994,22 +20114,37 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
const_reference at(const typename object_t::key_type& key) const
|
||||
{
|
||||
// at only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
JSON_TRY
|
||||
{
|
||||
return m_value.object->at(key);
|
||||
}
|
||||
JSON_CATCH (std::out_of_range&)
|
||||
{
|
||||
// create better exception explanation
|
||||
JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
|
||||
}
|
||||
}
|
||||
else
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
|
||||
}
|
||||
|
||||
auto it = m_value.object->find(key);
|
||||
if (it == m_value.object->end())
|
||||
{
|
||||
JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
/// @brief access specified object element with bounds checking
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/at/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
const_reference at(KeyType && key) const
|
||||
{
|
||||
// at only works for objects
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
|
||||
}
|
||||
|
||||
auto it = m_value.object->find(std::forward<KeyType>(key));
|
||||
if (it == m_value.object->end())
|
||||
{
|
||||
JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
/// @brief access specified array element
|
||||
@ -20073,7 +20208,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// @brief access specified object element
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
|
||||
reference operator[](const typename object_t::key_type& key)
|
||||
reference operator[](typename object_t::key_type key)
|
||||
{
|
||||
// implicitly convert null value to an empty object
|
||||
if (is_null())
|
||||
@ -20086,7 +20221,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
// operator[] only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
return set_parent(m_value.object->operator[](key));
|
||||
auto result = m_value.object->emplace(std::move(key), nullptr);
|
||||
return set_parent(result.first->second);
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
|
||||
@ -20099,31 +20235,47 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
// const operator[] only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
|
||||
return m_value.object->find(key)->second;
|
||||
auto it = m_value.object->find(key);
|
||||
JSON_ASSERT(it != m_value.object->end());
|
||||
return it->second;
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
|
||||
}
|
||||
|
||||
/// @brief access specified object element
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
|
||||
// these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
|
||||
// (they seemingly cannot be constrained to resolve the ambiguity)
|
||||
template<typename T>
|
||||
JSON_HEDLEY_NON_NULL(2)
|
||||
reference operator[](T* key)
|
||||
{
|
||||
// implicitly convert null to object
|
||||
return operator[](typename object_t::key_type(key));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const_reference operator[](T* key) const
|
||||
{
|
||||
return operator[](typename object_t::key_type(key));
|
||||
}
|
||||
|
||||
/// @brief access specified object element
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
reference operator[](KeyType && key)
|
||||
{
|
||||
// implicitly convert null value to an empty object
|
||||
if (is_null())
|
||||
{
|
||||
m_type = value_t::object;
|
||||
m_value = value_t::object;
|
||||
m_value.object = create<object_t>();
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
// at only works for objects
|
||||
// operator[] only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
return set_parent(m_value.object->operator[](key));
|
||||
auto result = m_value.object->emplace(std::forward<KeyType>(key), nullptr);
|
||||
return set_parent(result.first->second);
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
|
||||
@ -20131,15 +20283,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// @brief access specified object element
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
|
||||
template<typename T>
|
||||
JSON_HEDLEY_NON_NULL(2)
|
||||
const_reference operator[](T* key) const
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
const_reference operator[](KeyType && key) const
|
||||
{
|
||||
// at only works for objects
|
||||
// const operator[] only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
|
||||
return m_value.object->find(key)->second;
|
||||
auto it = m_value.object->find(std::forward<KeyType>(key));
|
||||
JSON_ASSERT(it != m_value.object->end());
|
||||
return it->second;
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
|
||||
@ -20147,23 +20300,24 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// @brief access specified object element with default value
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||
/// using std::is_convertible in a std::enable_if will fail when using explicit conversions
|
||||
template < class ValueType, typename std::enable_if <
|
||||
detail::is_getable<basic_json_t, ValueType>::value
|
||||
&& !std::is_same<value_t, ValueType>::value, int >::type = 0 >
|
||||
ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
|
||||
// this is the value(const typename object_t::key_type&) overload
|
||||
template < class KeyType, class ValueType, detail::enable_if_t <
|
||||
std::is_same<KeyType, typename object_t::key_type>::value
|
||||
&& detail::is_getable<basic_json_t, ValueType>::value
|
||||
&& !std::is_same<value_t, ValueType>::value, int > = 0 >
|
||||
typename std::decay<ValueType>::type value(const KeyType& key, ValueType && default_value) const
|
||||
{
|
||||
// at only works for objects
|
||||
// value only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
// if key is found, return value and given default value otherwise
|
||||
const auto it = find(key);
|
||||
if (it != end())
|
||||
{
|
||||
return it->template get<ValueType>();
|
||||
return it->template get<typename std::decay<ValueType>::type>();
|
||||
}
|
||||
|
||||
return default_value;
|
||||
return std::forward<ValueType>(default_value);
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
@ -20177,13 +20331,64 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
return value(key, string_t(default_value));
|
||||
}
|
||||
|
||||
// these two functions, in conjunction with value(const KeyType &, ValueType &&),
|
||||
// resolve an ambiguity that would otherwise occur between the json_pointer and
|
||||
// typename object_t::key_type & overloads
|
||||
template < class ValueType, detail::enable_if_t <
|
||||
detail::is_getable<basic_json_t, ValueType>::value
|
||||
&& !std::is_same<value_t, ValueType>::value, int > = 0 >
|
||||
typename std::decay<ValueType>::type value(const char* key, ValueType && default_value) const
|
||||
{
|
||||
return value(typename object_t::key_type(key), std::forward<ValueType>(default_value));
|
||||
}
|
||||
|
||||
string_t value(const char* key, const char* default_value) const
|
||||
{
|
||||
return value(typename object_t::key_type(key), string_t(default_value));
|
||||
}
|
||||
|
||||
/// @brief access specified object element with default value
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||
/// using std::is_convertible in a std::enable_if will fail when using explicit conversions
|
||||
template < class KeyType, class ValueType, detail::enable_if_t <
|
||||
detail::is_getable<basic_json_t, ValueType>::value
|
||||
&& !std::is_same<value_t, ValueType>::value
|
||||
&& detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
typename std::decay<ValueType>::type value(KeyType && key, ValueType && default_value) const
|
||||
{
|
||||
// value only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
// if key is found, return value and given default value otherwise
|
||||
const auto it = find(std::forward<KeyType>(key));
|
||||
if (it != end())
|
||||
{
|
||||
return it->template get<typename std::decay<ValueType>::type>();
|
||||
}
|
||||
|
||||
return std::forward<ValueType>(default_value);
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
}
|
||||
|
||||
/// @brief access specified object element with default value
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||
/// overload for a default value of type const char*
|
||||
template < class KeyType, detail::enable_if_t <
|
||||
!detail::is_json_pointer<KeyType>::value, int > = 0 >
|
||||
string_t value(KeyType && key, const char* default_value) const
|
||||
{
|
||||
return value(std::forward<KeyType>(key), string_t(default_value));
|
||||
}
|
||||
|
||||
/// @brief access specified object element via JSON Pointer with default value
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||
template<class ValueType, typename std::enable_if<
|
||||
detail::is_getable<basic_json_t, ValueType>::value, int>::type = 0>
|
||||
template < class ValueType, detail::enable_if_t <
|
||||
detail::is_getable<basic_json_t, ValueType>::value, int> = 0 >
|
||||
ValueType value(const json_pointer& ptr, const ValueType& default_value) const
|
||||
{
|
||||
// at only works for objects
|
||||
// value only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
// if pointer resolves a value, return it or use default value
|
||||
@ -20200,8 +20405,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
}
|
||||
|
||||
template<class ValueType, class BasicJsonType, typename std::enable_if<
|
||||
detail::is_getable<basic_json_t, ValueType>::value, int>::type = 0>
|
||||
template < class ValueType, class BasicJsonType, detail::enable_if_t <
|
||||
detail::is_getable<basic_json_t, ValueType>::value, int> = 0 >
|
||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
|
||||
ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
|
||||
{
|
||||
@ -20259,10 +20464,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// @brief remove element given an iterator
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/erase/
|
||||
template < class IteratorType, typename std::enable_if <
|
||||
template < class IteratorType, detail::enable_if_t <
|
||||
std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
|
||||
std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
|
||||
= 0 >
|
||||
std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
|
||||
IteratorType erase(IteratorType pos)
|
||||
{
|
||||
// make sure iterator fits the current value
|
||||
@ -20330,10 +20534,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// @brief remove elements given an iterator range
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/erase/
|
||||
template < class IteratorType, typename std::enable_if <
|
||||
template < class IteratorType, detail::enable_if_t <
|
||||
std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
|
||||
std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
|
||||
= 0 >
|
||||
std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
|
||||
IteratorType erase(IteratorType first, IteratorType last)
|
||||
{
|
||||
// make sure iterator fits the current value
|
||||
@ -20402,17 +20605,57 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
template < typename KeyType, detail::enable_if_t <
|
||||
detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
size_type erase_internal(KeyType && key)
|
||||
{
|
||||
// this erase only works for objects
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
|
||||
}
|
||||
|
||||
return m_value.object->erase(std::forward<KeyType>(key));
|
||||
}
|
||||
|
||||
template < typename KeyType, detail::enable_if_t <
|
||||
!detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
size_type erase_internal(KeyType && key)
|
||||
{
|
||||
// this erase only works for objects
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
|
||||
}
|
||||
|
||||
const auto it = m_value.object->find(std::forward<KeyType>(key));
|
||||
if (it != m_value.object->end())
|
||||
{
|
||||
m_value.object->erase(it);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// @brief remove element from a JSON object given a key
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/erase/
|
||||
size_type erase(const typename object_t::key_type& key)
|
||||
{
|
||||
// this erase only works for objects
|
||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||
{
|
||||
return m_value.object->erase(key);
|
||||
}
|
||||
// the indirection via erase_internal() is added to avoid making this
|
||||
// function a template and thus de-rank it during overload resolution
|
||||
return erase_internal(key);
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
|
||||
/// @brief remove element from a JSON object given a key
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/erase/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
size_type erase(KeyType && key)
|
||||
{
|
||||
return erase_internal(std::forward<KeyType>(key));
|
||||
}
|
||||
|
||||
/// @brief remove element from a JSON array given an index
|
||||
@ -20447,14 +20690,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// @brief find an element in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/find/
|
||||
template<typename KeyT>
|
||||
iterator find(KeyT&& key)
|
||||
iterator find(const typename object_t::key_type& key)
|
||||
{
|
||||
auto result = end();
|
||||
|
||||
if (is_object())
|
||||
{
|
||||
result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
|
||||
result.m_it.object_iterator = m_value.object->find(key);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -20462,14 +20704,45 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// @brief find an element in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/find/
|
||||
template<typename KeyT>
|
||||
const_iterator find(KeyT&& key) const
|
||||
const_iterator find(const typename object_t::key_type& key) const
|
||||
{
|
||||
auto result = cend();
|
||||
|
||||
if (is_object())
|
||||
{
|
||||
result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
|
||||
result.m_it.object_iterator = m_value.object->find(key);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// @brief find an element in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/find/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
iterator find(KeyType && key)
|
||||
{
|
||||
auto result = end();
|
||||
|
||||
if (is_object())
|
||||
{
|
||||
result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// @brief find an element in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/find/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
const_iterator find(KeyType && key) const
|
||||
{
|
||||
auto result = cend();
|
||||
|
||||
if (is_object())
|
||||
{
|
||||
result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key));
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -20477,20 +20750,36 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// @brief returns the number of occurrences of a key in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/count/
|
||||
template<typename KeyT>
|
||||
size_type count(KeyT&& key) const
|
||||
size_type count(const typename object_t::key_type& key) const
|
||||
{
|
||||
// return 0 for all nonobject types
|
||||
return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
|
||||
return is_object() ? m_value.object->count(key) : 0;
|
||||
}
|
||||
|
||||
/// @brief returns the number of occurrences of a key in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/count/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
size_type count(KeyType && key) const
|
||||
{
|
||||
// return 0 for all nonobject types
|
||||
return is_object() ? m_value.object->count(std::forward<KeyType>(key)) : 0;
|
||||
}
|
||||
|
||||
/// @brief check the existence of an element in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/contains/
|
||||
template < typename KeyT, typename std::enable_if <
|
||||
!detail::is_json_pointer<typename std::decay<KeyT>::type>::value, int >::type = 0 >
|
||||
bool contains(KeyT && key) const
|
||||
bool contains(const typename object_t::key_type& key) const
|
||||
{
|
||||
return is_object() && m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
|
||||
return is_object() && m_value.object->find(key) != m_value.object->end();
|
||||
}
|
||||
|
||||
/// @brief check the existence of an element in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/contains/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
bool contains(KeyType && key) const
|
||||
{
|
||||
return is_object() && m_value.object->find(std::forward<KeyType>(key)) != m_value.object->end();
|
||||
}
|
||||
|
||||
/// @brief check the existence of an element in a JSON object given a JSON pointer
|
||||
@ -22276,7 +22565,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
return ptr.get_unchecked(this);
|
||||
}
|
||||
|
||||
template<typename BasicJsonType>
|
||||
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
|
||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
|
||||
reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
|
||||
{
|
||||
@ -22290,7 +22579,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
return ptr.get_unchecked(this);
|
||||
}
|
||||
|
||||
template<typename BasicJsonType>
|
||||
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
|
||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
|
||||
const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
|
||||
{
|
||||
@ -22892,6 +23181,7 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std
|
||||
#undef NLOHMANN_BASIC_JSON_TPL
|
||||
#undef JSON_EXPLICIT
|
||||
#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
|
||||
#undef JSON_NO_UNIQUE_ADDRESS
|
||||
|
||||
#ifndef JSON_TEST_KEEP_MACROS
|
||||
#undef JSON_CATCH
|
||||
|
@ -60,12 +60,38 @@ TEST_CASE("element access 2")
|
||||
CHECK(j_const.at("floating") == json(42.23));
|
||||
CHECK(j_const.at("object") == json::object());
|
||||
CHECK(j_const.at("array") == json({1, 2, 3}));
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j.at(std::string_view("integer")) == json(1));
|
||||
CHECK(j.at(std::string_view("unsigned")) == json(1u));
|
||||
CHECK(j.at(std::string_view("boolean")) == json(true));
|
||||
CHECK(j.at(std::string_view("null")) == json(nullptr));
|
||||
CHECK(j.at(std::string_view("string")) == json("hello world"));
|
||||
CHECK(j.at(std::string_view("floating")) == json(42.23));
|
||||
CHECK(j.at(std::string_view("object")) == json::object());
|
||||
CHECK(j.at(std::string_view("array")) == json({1, 2, 3}));
|
||||
|
||||
CHECK(j_const.at(std::string_view("integer")) == json(1));
|
||||
CHECK(j_const.at(std::string_view("unsigned")) == json(1u));
|
||||
CHECK(j_const.at(std::string_view("boolean")) == json(true));
|
||||
CHECK(j_const.at(std::string_view("null")) == json(nullptr));
|
||||
CHECK(j_const.at(std::string_view("string")) == json("hello world"));
|
||||
CHECK(j_const.at(std::string_view("floating")) == json(42.23));
|
||||
CHECK(j_const.at(std::string_view("object")) == json::object());
|
||||
CHECK(j_const.at(std::string_view("array")) == json({1, 2, 3}));
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("access outside bounds")
|
||||
{
|
||||
CHECK_THROWS_WITH_AS(j.at("foo"), "[json.exception.out_of_range.403] key 'foo' not found", json::out_of_range&);
|
||||
CHECK_THROWS_WITH_AS(j_const.at("foo"), "[json.exception.out_of_range.403] key 'foo' not found", json::out_of_range&);
|
||||
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j.at(std::string_view("foo")), "[json.exception.out_of_range.403] key 'foo' not found", json::out_of_range&);
|
||||
CHECK_THROWS_WITH_AS(j_const.at(std::string_view("foo")), "[json.exception.out_of_range.403] key 'foo' not found", json::out_of_range&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("access on non-object type")
|
||||
@ -76,6 +102,11 @@ TEST_CASE("element access 2")
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with null", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with null", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.at(std::string_view(std::string_view("foo"))), "[json.exception.type_error.304] cannot use at() with null", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.at(std::string_view(std::string_view("foo"))), "[json.exception.type_error.304] cannot use at() with null", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
@ -84,6 +115,11 @@ TEST_CASE("element access 2")
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with boolean", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with boolean", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with boolean", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with boolean", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
@ -92,6 +128,11 @@ TEST_CASE("element access 2")
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with string", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with string", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with string", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with string", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
@ -100,6 +141,11 @@ TEST_CASE("element access 2")
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with array", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with array", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with array", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with array", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
@ -108,6 +154,11 @@ TEST_CASE("element access 2")
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with number", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with number", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with number", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with number", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
@ -116,6 +167,11 @@ TEST_CASE("element access 2")
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with number", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with number", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with number", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with number", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
@ -124,6 +180,11 @@ TEST_CASE("element access 2")
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with number", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with number", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with number", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.at(std::string_view("foo")), "[json.exception.type_error.304] cannot use at() with number", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -158,6 +219,33 @@ TEST_CASE("element access 2")
|
||||
CHECK(j_const.value("floating", 12) == 42);
|
||||
CHECK(j_const.value("object", json({{"foo", "bar"}})) == json::object());
|
||||
CHECK(j_const.value("array", json({10, 100})) == json({1, 2, 3}));
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j.value(std::string_view("integer"), 2) == 1);
|
||||
CHECK(j.value(std::string_view("integer"), 1.0) == Approx(1));
|
||||
CHECK(j.value(std::string_view("unsigned"), 2) == 1u);
|
||||
CHECK(j.value(std::string_view("unsigned"), 1.0) == Approx(1u));
|
||||
CHECK(j.value(std::string_view("null"), json(1)) == json());
|
||||
CHECK(j.value(std::string_view("boolean"), false) == true);
|
||||
CHECK(j.value(std::string_view("string"), "bar") == "hello world");
|
||||
CHECK(j.value(std::string_view("string"), std::string("bar")) == "hello world");
|
||||
CHECK(j.value(std::string_view("floating"), 12.34) == Approx(42.23));
|
||||
CHECK(j.value(std::string_view("floating"), 12) == 42);
|
||||
CHECK(j.value(std::string_view("object"), json({{"foo", "bar"}})) == json::object());
|
||||
CHECK(j.value(std::string_view("array"), json({10, 100})) == json({1, 2, 3}));
|
||||
|
||||
CHECK(j_const.value(std::string_view("integer"), 2) == 1);
|
||||
CHECK(j_const.value(std::string_view("integer"), 1.0) == Approx(1));
|
||||
CHECK(j_const.value(std::string_view("unsigned"), 2) == 1u);
|
||||
CHECK(j_const.value(std::string_view("unsigned"), 1.0) == Approx(1u));
|
||||
CHECK(j_const.value(std::string_view("boolean"), false) == true);
|
||||
CHECK(j_const.value(std::string_view("string"), "bar") == "hello world");
|
||||
CHECK(j_const.value(std::string_view("string"), std::string("bar")) == "hello world");
|
||||
CHECK(j_const.value(std::string_view("floating"), 12.34) == Approx(42.23));
|
||||
CHECK(j_const.value(std::string_view("floating"), 12) == 42);
|
||||
CHECK(j_const.value(std::string_view("object"), json({{"foo", "bar"}})) == json::object());
|
||||
CHECK(j_const.value(std::string_view("array"), json({10, 100})) == json({1, 2, 3}));
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("access non-existing value")
|
||||
@ -177,6 +265,24 @@ TEST_CASE("element access 2")
|
||||
CHECK(j_const.value("_", 12.34) == Approx(12.34));
|
||||
CHECK(j_const.value("_", json({{"foo", "bar"}})) == json({{"foo", "bar"}}));
|
||||
CHECK(j_const.value("_", json({10, 100})) == json({10, 100}));
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j.value(std::string_view("_"), 2) == 2);
|
||||
CHECK(j.value(std::string_view("_"), 2u) == 2u);
|
||||
CHECK(j.value(std::string_view("_"), false) == false);
|
||||
CHECK(j.value(std::string_view("_"), "bar") == "bar");
|
||||
CHECK(j.value(std::string_view("_"), 12.34) == Approx(12.34));
|
||||
CHECK(j.value(std::string_view("_"), json({{"foo", "bar"}})) == json({{"foo", "bar"}}));
|
||||
CHECK(j.value(std::string_view("_"), json({10, 100})) == json({10, 100}));
|
||||
|
||||
CHECK(j_const.value(std::string_view("_"), 2) == 2);
|
||||
CHECK(j_const.value(std::string_view("_"), 2u) == 2u);
|
||||
CHECK(j_const.value(std::string_view("_"), false) == false);
|
||||
CHECK(j_const.value(std::string_view("_"), "bar") == "bar");
|
||||
CHECK(j_const.value(std::string_view("_"), 12.34) == Approx(12.34));
|
||||
CHECK(j_const.value(std::string_view("_"), json({{"foo", "bar"}})) == json({{"foo", "bar"}}));
|
||||
CHECK(j_const.value(std::string_view("_"), json({10, 100})) == json({10, 100}));
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("access on non-object type")
|
||||
@ -187,6 +293,11 @@ TEST_CASE("element access 2")
|
||||
const json j_nonobject_const(json::value_t::null);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with null", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.value("foo", 1), "[json.exception.type_error.306] cannot use value() with null", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with null", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with null", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
@ -195,6 +306,11 @@ TEST_CASE("element access 2")
|
||||
const json j_nonobject_const(json::value_t::boolean);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with boolean", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.value("foo", 1), "[json.exception.type_error.306] cannot use value() with boolean", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with boolean", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with boolean", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
@ -203,6 +319,11 @@ TEST_CASE("element access 2")
|
||||
const json j_nonobject_const(json::value_t::string);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with string", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.value("foo", 1), "[json.exception.type_error.306] cannot use value() with string", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with string", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with string", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
@ -211,6 +332,11 @@ TEST_CASE("element access 2")
|
||||
const json j_nonobject_const(json::value_t::array);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with array", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.value("foo", 1), "[json.exception.type_error.306] cannot use value() with array", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with array", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with array", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
@ -219,6 +345,11 @@ TEST_CASE("element access 2")
|
||||
const json j_nonobject_const(json::value_t::number_integer);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with number", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.value("foo", 1), "[json.exception.type_error.306] cannot use value() with number", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with number", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with number", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
@ -227,6 +358,11 @@ TEST_CASE("element access 2")
|
||||
const json j_nonobject_const(json::value_t::number_unsigned);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with number", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.value("foo", 1), "[json.exception.type_error.306] cannot use value() with number", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with number", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with number", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
@ -235,6 +371,11 @@ TEST_CASE("element access 2")
|
||||
const json j_nonobject_const(json::value_t::number_float);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with number", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.value("foo", 1), "[json.exception.type_error.306] cannot use value() with number", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with number", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject_const.value(std::string_view("foo"), 1), "[json.exception.type_error.306] cannot use value() with number", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -330,6 +471,31 @@ TEST_CASE("element access 2")
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("non-const operator[]")
|
||||
{
|
||||
{
|
||||
json j_null;
|
||||
CHECK(j_null.is_null());
|
||||
j_null["key"] = 1;
|
||||
CHECK(j_null.is_object());
|
||||
CHECK(j_null.size() == 1);
|
||||
j_null["key"] = 2;
|
||||
CHECK(j_null.size() == 1);
|
||||
}
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
{
|
||||
std::string_view key = "key";
|
||||
json j_null;
|
||||
CHECK(j_null.is_null());
|
||||
j_null[key] = 1;
|
||||
CHECK(j_null.is_object());
|
||||
CHECK(j_null.size() == 1);
|
||||
j_null[key] = 2;
|
||||
CHECK(j_null.size() == 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("front and back")
|
||||
{
|
||||
// "array" is the smallest key
|
||||
@ -390,6 +556,56 @@ TEST_CASE("element access 2")
|
||||
CHECK(j_const[json::object_t::key_type("array")] == j["array"]);
|
||||
}
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
SECTION("access within bounds (string_view)")
|
||||
{
|
||||
CHECK(j["integer"] == json(1));
|
||||
CHECK(j[std::string_view("integer")] == j["integer"]);
|
||||
|
||||
CHECK(j["unsigned"] == json(1u));
|
||||
CHECK(j[std::string_view("unsigned")] == j["unsigned"]);
|
||||
|
||||
CHECK(j["boolean"] == json(true));
|
||||
CHECK(j[std::string_view("boolean")] == j["boolean"]);
|
||||
|
||||
CHECK(j["null"] == json(nullptr));
|
||||
CHECK(j[std::string_view("null")] == j["null"]);
|
||||
|
||||
CHECK(j["string"] == json("hello world"));
|
||||
CHECK(j[std::string_view("string")] == j["string"]);
|
||||
|
||||
CHECK(j["floating"] == json(42.23));
|
||||
CHECK(j[std::string_view("floating")] == j["floating"]);
|
||||
|
||||
CHECK(j["object"] == json::object());
|
||||
CHECK(j[std::string_view("object")] == j["object"]);
|
||||
|
||||
CHECK(j["array"] == json({1, 2, 3}));
|
||||
CHECK(j[std::string_view("array")] == j["array"]);
|
||||
|
||||
CHECK(j_const["integer"] == json(1));
|
||||
CHECK(j_const[std::string_view("integer")] == j["integer"]);
|
||||
|
||||
CHECK(j_const["boolean"] == json(true));
|
||||
CHECK(j_const[std::string_view("boolean")] == j["boolean"]);
|
||||
|
||||
CHECK(j_const["null"] == json(nullptr));
|
||||
CHECK(j_const[std::string_view("null")] == j["null"]);
|
||||
|
||||
CHECK(j_const["string"] == json("hello world"));
|
||||
CHECK(j_const[std::string_view("string")] == j["string"]);
|
||||
|
||||
CHECK(j_const["floating"] == json(42.23));
|
||||
CHECK(j_const[std::string_view("floating")] == j["floating"]);
|
||||
|
||||
CHECK(j_const["object"] == json::object());
|
||||
CHECK(j_const[std::string_view("object")] == j["object"]);
|
||||
|
||||
CHECK(j_const["array"] == json({1, 2, 3}));
|
||||
CHECK(j_const[std::string_view("array")] == j["array"]);
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("access on non-object type")
|
||||
{
|
||||
SECTION("null")
|
||||
@ -397,10 +613,16 @@ TEST_CASE("element access 2")
|
||||
json j_nonobject(json::value_t::null);
|
||||
json j_nonobject2(json::value_t::null);
|
||||
const json j_const_nonobject(j_nonobject);
|
||||
|
||||
CHECK_NOTHROW(j_nonobject["foo"]);
|
||||
CHECK_NOTHROW(j_nonobject2[json::object_t::key_type("foo")]);
|
||||
CHECK_THROWS_WITH_AS(j_const_nonobject["foo"], "[json.exception.type_error.305] cannot use operator[] with a string argument with null", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_const_nonobject[json::object_t::key_type("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with null", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_NOTHROW(j_nonobject2[std::string_view("foo")]);
|
||||
CHECK_THROWS_WITH_AS(j_const_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with null", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
@ -415,6 +637,11 @@ TEST_CASE("element access 2")
|
||||
"[json.exception.type_error.305] cannot use operator[] with a string argument with boolean", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_const_nonobject[json::object_t::key_type("foo")],
|
||||
"[json.exception.type_error.305] cannot use operator[] with a string argument with boolean", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with boolean", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_const_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with boolean", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
@ -429,6 +656,11 @@ TEST_CASE("element access 2")
|
||||
"[json.exception.type_error.305] cannot use operator[] with a string argument with string", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_const_nonobject[json::object_t::key_type("foo")],
|
||||
"[json.exception.type_error.305] cannot use operator[] with a string argument with string", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with string", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_const_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with string", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
@ -442,6 +674,11 @@ TEST_CASE("element access 2")
|
||||
"[json.exception.type_error.305] cannot use operator[] with a string argument with array", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_const_nonobject[json::object_t::key_type("foo")],
|
||||
"[json.exception.type_error.305] cannot use operator[] with a string argument with array", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with array", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_const_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with array", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
@ -456,6 +693,11 @@ TEST_CASE("element access 2")
|
||||
"[json.exception.type_error.305] cannot use operator[] with a string argument with number", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_const_nonobject[json::object_t::key_type("foo")],
|
||||
"[json.exception.type_error.305] cannot use operator[] with a string argument with number", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with number", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_const_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with number", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
@ -470,6 +712,11 @@ TEST_CASE("element access 2")
|
||||
"[json.exception.type_error.305] cannot use operator[] with a string argument with number", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_const_nonobject[json::object_t::key_type("foo")],
|
||||
"[json.exception.type_error.305] cannot use operator[] with a string argument with number", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with number", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_const_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with number", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
@ -484,6 +731,11 @@ TEST_CASE("element access 2")
|
||||
"[json.exception.type_error.305] cannot use operator[] with a string argument with number", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_const_nonobject[json::object_t::key_type("foo")],
|
||||
"[json.exception.type_error.305] cannot use operator[] with a string argument with number", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with number", json::type_error&);
|
||||
CHECK_THROWS_WITH_AS(j_const_nonobject[std::string_view("foo")], "[json.exception.type_error.305] cannot use operator[] with a string argument with number", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -533,6 +785,51 @@ TEST_CASE("element access 2")
|
||||
CHECK(j.erase("array") == 0);
|
||||
}
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
SECTION("remove element by key (string_view)")
|
||||
{
|
||||
CHECK(j.find(std::string_view("integer")) != j.end());
|
||||
CHECK(j.erase(std::string_view("integer")) == 1);
|
||||
CHECK(j.find(std::string_view("integer")) == j.end());
|
||||
CHECK(j.erase(std::string_view("integer")) == 0);
|
||||
|
||||
CHECK(j.find(std::string_view("unsigned")) != j.end());
|
||||
CHECK(j.erase(std::string_view("unsigned")) == 1);
|
||||
CHECK(j.find(std::string_view("unsigned")) == j.end());
|
||||
CHECK(j.erase(std::string_view("unsigned")) == 0);
|
||||
|
||||
CHECK(j.find(std::string_view("boolean")) != j.end());
|
||||
CHECK(j.erase(std::string_view("boolean")) == 1);
|
||||
CHECK(j.find(std::string_view("boolean")) == j.end());
|
||||
CHECK(j.erase(std::string_view("boolean")) == 0);
|
||||
|
||||
CHECK(j.find(std::string_view("null")) != j.end());
|
||||
CHECK(j.erase(std::string_view("null")) == 1);
|
||||
CHECK(j.find(std::string_view("null")) == j.end());
|
||||
CHECK(j.erase(std::string_view("null")) == 0);
|
||||
|
||||
CHECK(j.find(std::string_view("string")) != j.end());
|
||||
CHECK(j.erase(std::string_view("string")) == 1);
|
||||
CHECK(j.find(std::string_view("string")) == j.end());
|
||||
CHECK(j.erase(std::string_view("string")) == 0);
|
||||
|
||||
CHECK(j.find(std::string_view("floating")) != j.end());
|
||||
CHECK(j.erase(std::string_view("floating")) == 1);
|
||||
CHECK(j.find(std::string_view("floating")) == j.end());
|
||||
CHECK(j.erase(std::string_view("floating")) == 0);
|
||||
|
||||
CHECK(j.find(std::string_view("object")) != j.end());
|
||||
CHECK(j.erase(std::string_view("object")) == 1);
|
||||
CHECK(j.find(std::string_view("object")) == j.end());
|
||||
CHECK(j.erase(std::string_view("object")) == 0);
|
||||
|
||||
CHECK(j.find(std::string_view("array")) != j.end());
|
||||
CHECK(j.erase(std::string_view("array")) == 1);
|
||||
CHECK(j.find(std::string_view("array")) == j.end());
|
||||
CHECK(j.erase(std::string_view("array")) == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("remove element by iterator")
|
||||
{
|
||||
SECTION("erase(begin())")
|
||||
@ -652,36 +949,60 @@ TEST_CASE("element access 2")
|
||||
{
|
||||
json j_nonobject(json::value_t::null);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with null", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.erase(std::string_view("foo")), "[json.exception.type_error.307] cannot use erase() with null", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j_nonobject(json::value_t::boolean);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with boolean", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.erase(std::string_view("foo")), "[json.exception.type_error.307] cannot use erase() with boolean", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j_nonobject(json::value_t::string);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with string", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.erase(std::string_view("foo")), "[json.exception.type_error.307] cannot use erase() with string", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j_nonobject(json::value_t::array);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with array", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.erase(std::string_view("foo")), "[json.exception.type_error.307] cannot use erase() with array", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_integer);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with number", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.erase(std::string_view("foo")), "[json.exception.type_error.307] cannot use erase() with number", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_float);
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with number", json::type_error&);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK_THROWS_WITH_AS(j_nonobject.erase(std::string_view("foo")), "[json.exception.type_error.307] cannot use erase() with number", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -699,12 +1020,28 @@ TEST_CASE("element access 2")
|
||||
CHECK(j_const.find(key) != j_const.end());
|
||||
CHECK(*j_const.find(key) == j_const.at(key));
|
||||
}
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
for (const std::string_view key :
|
||||
{"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array"
|
||||
})
|
||||
{
|
||||
CHECK(j.find(key) != j.end());
|
||||
CHECK(*j.find(key) == j.at(key));
|
||||
CHECK(j_const.find(key) != j_const.end());
|
||||
CHECK(*j_const.find(key) == j_const.at(key));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("nonexisting element")
|
||||
{
|
||||
CHECK(j.find("foo") == j.end());
|
||||
CHECK(j_const.find("foo") == j_const.end());
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j.find(std::string_view("foo")) == j.end());
|
||||
CHECK(j_const.find(std::string_view("foo")) == j_const.end());
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("all types")
|
||||
@ -713,64 +1050,112 @@ TEST_CASE("element access 2")
|
||||
{
|
||||
json j_nonarray(json::value_t::null);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
|
||||
CHECK(j_nonarray.find("foo") == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j_nonarray.find(std::string_view("foo")) == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find(std::string_view("foo")) == j_nonarray_const.end());
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j_nonarray(json::value_t::string);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
|
||||
CHECK(j_nonarray.find("foo") == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j_nonarray.find(std::string_view("foo")) == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find(std::string_view("foo")) == j_nonarray_const.end());
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j_nonarray(json::value_t::object);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
|
||||
CHECK(j_nonarray.find("foo") == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j_nonarray.find(std::string_view("foo")) == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find(std::string_view("foo")) == j_nonarray_const.end());
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j_nonarray(json::value_t::array);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
|
||||
CHECK(j_nonarray.find("foo") == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j_nonarray.find(std::string_view("foo")) == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find(std::string_view("foo")) == j_nonarray_const.end());
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j_nonarray(json::value_t::boolean);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
|
||||
CHECK(j_nonarray.find("foo") == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j_nonarray.find(std::string_view("foo")) == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find(std::string_view("foo")) == j_nonarray_const.end());
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j_nonarray(json::value_t::number_integer);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
|
||||
CHECK(j_nonarray.find("foo") == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j_nonarray.find(std::string_view("foo")) == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find(std::string_view("foo")) == j_nonarray_const.end());
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j_nonarray(json::value_t::number_unsigned);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
|
||||
CHECK(j_nonarray.find("foo") == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j_nonarray.find(std::string_view("foo")) == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find(std::string_view("foo")) == j_nonarray_const.end());
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
{
|
||||
json j_nonarray(json::value_t::number_float);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
|
||||
CHECK(j_nonarray.find("foo") == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j_nonarray.find(std::string_view("foo")) == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find(std::string_view("foo")) == j_nonarray_const.end());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -786,12 +1171,26 @@ TEST_CASE("element access 2")
|
||||
CHECK(j.count(key) == 1);
|
||||
CHECK(j_const.count(key) == 1);
|
||||
}
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
for (const std::string_view key :
|
||||
{"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array"
|
||||
})
|
||||
{
|
||||
CHECK(j.count(key) == 1);
|
||||
CHECK(j_const.count(key) == 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("nonexisting element")
|
||||
{
|
||||
CHECK(j.count("foo") == 0);
|
||||
CHECK(j_const.count("foo") == 0);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j.count(std::string_view("foo")) == 0);
|
||||
CHECK(j_const.count(std::string_view("foo")) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("all types")
|
||||
@ -800,64 +1199,112 @@ TEST_CASE("element access 2")
|
||||
{
|
||||
json j_nonobject(json::value_t::null);
|
||||
const json j_nonobject_const(json::value_t::null);
|
||||
|
||||
CHECK(j_nonobject.count("foo") == 0);
|
||||
CHECK(j_nonobject_const.count("foo") == 0);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j.count(std::string_view("foo")) == 0);
|
||||
CHECK(j_const.count(std::string_view("foo")) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j_nonobject(json::value_t::string);
|
||||
const json j_nonobject_const(json::value_t::string);
|
||||
|
||||
CHECK(j_nonobject.count("foo") == 0);
|
||||
CHECK(j_nonobject_const.count("foo") == 0);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j.count(std::string_view("foo")) == 0);
|
||||
CHECK(j_const.count(std::string_view("foo")) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j_nonobject(json::value_t::object);
|
||||
const json j_nonobject_const(json::value_t::object);
|
||||
|
||||
CHECK(j_nonobject.count("foo") == 0);
|
||||
CHECK(j_nonobject_const.count("foo") == 0);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j.count(std::string_view("foo")) == 0);
|
||||
CHECK(j_const.count(std::string_view("foo")) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j_nonobject(json::value_t::array);
|
||||
const json j_nonobject_const(json::value_t::array);
|
||||
|
||||
CHECK(j_nonobject.count("foo") == 0);
|
||||
CHECK(j_nonobject_const.count("foo") == 0);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j.count(std::string_view("foo")) == 0);
|
||||
CHECK(j_const.count(std::string_view("foo")) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j_nonobject(json::value_t::boolean);
|
||||
const json j_nonobject_const(json::value_t::boolean);
|
||||
|
||||
CHECK(j_nonobject.count("foo") == 0);
|
||||
CHECK(j_nonobject_const.count("foo") == 0);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j.count(std::string_view("foo")) == 0);
|
||||
CHECK(j_const.count(std::string_view("foo")) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_integer);
|
||||
const json j_nonobject_const(json::value_t::number_integer);
|
||||
|
||||
CHECK(j_nonobject.count("foo") == 0);
|
||||
CHECK(j_nonobject_const.count("foo") == 0);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j.count(std::string_view("foo")) == 0);
|
||||
CHECK(j_const.count(std::string_view("foo")) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_unsigned);
|
||||
const json j_nonobject_const(json::value_t::number_unsigned);
|
||||
|
||||
CHECK(j_nonobject.count("foo") == 0);
|
||||
CHECK(j_nonobject_const.count("foo") == 0);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j.count(std::string_view("foo")) == 0);
|
||||
CHECK(j_const.count(std::string_view("foo")) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_float);
|
||||
const json j_nonobject_const(json::value_t::number_float);
|
||||
|
||||
CHECK(j_nonobject.count("foo") == 0);
|
||||
CHECK(j_nonobject_const.count("foo") == 0);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j.count(std::string_view("foo")) == 0);
|
||||
CHECK(j_const.count(std::string_view("foo")) == 0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -873,12 +1320,27 @@ TEST_CASE("element access 2")
|
||||
CHECK(j.contains(key) == true);
|
||||
CHECK(j_const.contains(key) == true);
|
||||
}
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
for (const std::string_view key :
|
||||
{"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array"
|
||||
})
|
||||
{
|
||||
CHECK(j.contains(key) == true);
|
||||
CHECK(j_const.contains(key) == true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("nonexisting element")
|
||||
{
|
||||
CHECK(j.contains("foo") == false);
|
||||
CHECK(j_const.contains("foo") == false);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j.contains(std::string_view("foo")) == false);
|
||||
CHECK(j_const.contains(std::string_view("foo")) == false);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("all types")
|
||||
@ -887,56 +1349,98 @@ TEST_CASE("element access 2")
|
||||
{
|
||||
json j_nonobject(json::value_t::null);
|
||||
const json j_nonobject_const(json::value_t::null);
|
||||
|
||||
CHECK(j_nonobject.contains("foo") == false);
|
||||
CHECK(j_nonobject_const.contains("foo") == false);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j_nonobject.contains(std::string_view("foo")) == false);
|
||||
CHECK(j_nonobject_const.contains(std::string_view("foo")) == false);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j_nonobject(json::value_t::string);
|
||||
const json j_nonobject_const(json::value_t::string);
|
||||
|
||||
CHECK(j_nonobject.contains("foo") == false);
|
||||
CHECK(j_nonobject_const.contains("foo") == false);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j_nonobject.contains(std::string_view("foo")) == false);
|
||||
CHECK(j_nonobject_const.contains(std::string_view("foo")) == false);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j_nonobject(json::value_t::object);
|
||||
const json j_nonobject_const(json::value_t::object);
|
||||
|
||||
CHECK(j_nonobject.contains("foo") == false);
|
||||
CHECK(j_nonobject_const.contains("foo") == false);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j_nonobject.contains(std::string_view("foo")) == false);
|
||||
CHECK(j_nonobject_const.contains(std::string_view("foo")) == false);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j_nonobject(json::value_t::array);
|
||||
const json j_nonobject_const(json::value_t::array);
|
||||
|
||||
CHECK(j_nonobject.contains("foo") == false);
|
||||
CHECK(j_nonobject_const.contains("foo") == false);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j_nonobject.contains(std::string_view("foo")) == false);
|
||||
CHECK(j_nonobject_const.contains(std::string_view("foo")) == false);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j_nonobject(json::value_t::boolean);
|
||||
const json j_nonobject_const(json::value_t::boolean);
|
||||
|
||||
CHECK(j_nonobject.contains("foo") == false);
|
||||
CHECK(j_nonobject_const.contains("foo") == false);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j_nonobject.contains(std::string_view("foo")) == false);
|
||||
CHECK(j_nonobject_const.contains(std::string_view("foo")) == false);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_integer);
|
||||
const json j_nonobject_const(json::value_t::number_integer);
|
||||
|
||||
CHECK(j_nonobject.contains("foo") == false);
|
||||
CHECK(j_nonobject_const.contains("foo") == false);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j_nonobject.contains(std::string_view("foo")) == false);
|
||||
CHECK(j_nonobject_const.contains(std::string_view("foo")) == false);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_unsigned);
|
||||
const json j_nonobject_const(json::value_t::number_unsigned);
|
||||
|
||||
CHECK(j_nonobject.contains("foo") == false);
|
||||
CHECK(j_nonobject_const.contains("foo") == false);
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j_nonobject.contains(std::string_view("foo")) == false);
|
||||
CHECK(j_nonobject_const.contains(std::string_view("foo")) == false);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
@ -945,6 +1449,10 @@ TEST_CASE("element access 2")
|
||||
const json j_nonobject_const(json::value_t::number_float);
|
||||
CHECK(j_nonobject.contains("foo") == false);
|
||||
CHECK(j_nonobject_const.contains("foo") == false);
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
CHECK(j_nonobject.contains(std::string_view("foo")) == false);
|
||||
CHECK(j_nonobject_const.contains(std::string_view("foo")) == false);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user