From 203b53d7cbec42ebb2b54cd998b1e5da858ae60d Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 29 Mar 2021 13:23:09 +0200 Subject: [PATCH] :bulb: update documentation --- cmake/ci.cmake | 1 + doc/mkdocs/docs/api/basic_json/at.md | 2 +- doc/mkdocs/docs/api/basic_json/erase.md | 4 +- doc/mkdocs/docs/api/basic_json/operator[].md | 5 +- doc/mkdocs/docs/api/basic_json/value.md | 8 +- include/nlohmann/json.hpp | 112 +++++++++++++++++-- single_include/nlohmann/json.hpp | 110 ++++++++++++++++-- test/src/unit-element_access2.cpp | 25 +++++ 8 files changed, 237 insertions(+), 30 deletions(-) diff --git a/cmake/ci.cmake b/cmake/ci.cmake index 5807d8f18..c968e2f17 100644 --- a/cmake/ci.cmake +++ b/cmake/ci.cmake @@ -470,6 +470,7 @@ add_custom_target(ci_test_coverage COMMAND CXX=${GCC_TOOL} ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_CXX_FLAGS="--coverage;-fprofile-arcs;-ftest-coverage" -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON + -DCMAKE_CXX_STANDARD=17 -DCMAKE_CXX_STANDARD_REQUIRED=ON -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_coverage COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_coverage COMMAND cd ${PROJECT_BINARY_DIR}/build_coverage && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure diff --git a/doc/mkdocs/docs/api/basic_json/at.md b/doc/mkdocs/docs/api/basic_json/at.md index 635a6efc5..66e001445 100644 --- a/doc/mkdocs/docs/api/basic_json/at.md +++ b/doc/mkdocs/docs/api/basic_json/at.md @@ -175,5 +175,5 @@ 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. +2. Added in version 1.0.0; `KeyT` template added in version 3.10.0. 3. Added in version 2.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/erase.md b/doc/mkdocs/docs/api/basic_json/erase.md index 43cde6dcc..160fe8f35 100644 --- a/doc/mkdocs/docs/api/basic_json/erase.md +++ b/doc/mkdocs/docs/api/basic_json/erase.md @@ -12,6 +12,7 @@ const_iterator erase(const_iterator first, const_iterator last); // (3) template size_type erase(KeyT && key); +size_type erase(const std::string_view& key); // since C++17 // (4) void erase(const size_type idx); @@ -35,7 +36,7 @@ void erase(const size_type idx); ## Template parameters `KeyT` -: A type convertible to an object key. This can also be a string literal or a string view (C++17). +: A type convertible to an object key. This can also be a string literal. ## Parameters @@ -181,3 +182,4 @@ Strong exception safety: if an exception occurs, the original value stays intact - Added in version 1.0.0. - Added support for binary types in version 3.8.0. +- Added `KeyT` template and overload for `std::string_view` in version 3.10.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator[].md b/doc/mkdocs/docs/api/basic_json/operator[].md index 20b98e0b9..f473a9e6b 100644 --- a/doc/mkdocs/docs/api/basic_json/operator[].md +++ b/doc/mkdocs/docs/api/basic_json/operator[].md @@ -14,6 +14,8 @@ template reference operator[](T* key); template const_reference operator[](T* key) const; +reference operator[](const std::string_view& key); // since C++17 +const_reference operator[](const std::string_view& key) const; // since C++17 // (3) reference operator[](const json_pointer& ptr); @@ -193,5 +195,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. +2. Added in version 1.0.0. Overloads for `T* key` added in version 1.1.0. Template and overload for `std::string_view` + added in version 3.10.0. 3. Added in version 2.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/value.md b/doc/mkdocs/docs/api/basic_json/value.md index 8fdbc238f..863bc44e2 100644 --- a/doc/mkdocs/docs/api/basic_json/value.md +++ b/doc/mkdocs/docs/api/basic_json/value.md @@ -2,8 +2,8 @@ ```cpp // (1) -template -ValueType value(const typename object_t::key_type& key, +template +ValueType value(const KeyType& key, const ValueType& default_value) const; // (2) @@ -41,6 +41,8 @@ Unlike [`operator[]`](operator[].md), this function does not implicitly add an e ## Template parameters +`KeyType` +: A type for an object key. This can also be a string literal or 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 @@ -118,4 +120,4 @@ changes to any JSON value. ## Version history 1. Added in version 1.0.0. -2. Added in version 2.0.2. +2. Added in version 2.0.2. `KeyType` template parameter added in 3.10.0. diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index b49576c8a..25a591a4f 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -1060,10 +1060,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec default: { object = nullptr; // silence warning, see #821 + // LCOV_EXCL_START if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) { - JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.9.1", basic_json())); // LCOV_EXCL_LINE + JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.9.1", basic_json())); } + // LCOV_EXCL_STOP break; } } @@ -3487,7 +3489,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec access by reference @sa see @ref value() for access by value with a default value - @since version 1.0.0 + @since version 1.0.0; template added in version 3.10.0 @liveexample{The example below shows how object elements can be read and written using `at()`. It also demonstrates the different exceptions that @@ -3540,7 +3542,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec access by reference @sa see @ref value() for access by value with a default value - @since version 1.0.0 + @since version 1.0.0; template added in version 3.10.0 @liveexample{The example below shows how object elements can be read using `at()`. It also demonstrates the different exceptions that can be thrown., @@ -3667,7 +3669,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec In case the value was `null` before, it is converted to an object. @param[in] key key of the element to access - @tparam KeyT a type convertible to an object key, excluding `std::string_view` + @tparam KeyT a type convertible to an object key @return reference to the element at key @a key @@ -3683,7 +3685,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec with range checking @sa see @ref value() for access by value with a default value - @since version 1.0.0 + @since version 1.0.0; template added in version 3.10.0 */ template < class KeyT, typename std::enable_if < !std::is_same::type, json_pointer>::value&& @@ -3711,7 +3713,33 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } #if defined(JSON_HAS_CPP_17) - /// @copydoc operator[](KeyT&&) + /*! + @brief access specified object element + + Returns a reference to the element at with specified key @a key. + + @note If @a key is not found in the object, then it is silently added to + the object and filled with a `null` value to make `key` a valid reference. + In case the value was `null` before, it is converted to an object. + + @param[in] key key of the element to access + + @return reference to the element at key @a key + + @throw type_error.305 if the JSON value is not an object or null; in that + cases, using the [] operator with a key makes no sense. + + @complexity Logarithmic in the size of the container. + + @liveexample{The example below shows how object elements can be read and + written using the `[]` operator.,operatorarray__key_type} + + @sa see @ref at(const typename object_t::key_type&) for access by reference + with range checking + @sa see @ref value() for access by value with a default value + + @since version 3.10.0 + */ reference operator[](const std::string_view& key) { // implicitly convert null value to an empty object @@ -3749,7 +3777,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec undefined. @param[in] key key of the element to access - @tparam KeyT a type convertible to an object key or, excluding `std::string_view` + @tparam KeyT a type convertible to an object key or @return const reference to the element at key @a key @@ -3768,7 +3796,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec with range checking @sa see @ref value() for access by value with a default value - @since version 1.0.0 + @since version 1.0.0; template added in version 3.10.0 */ template < class KeyT, typename std::enable_if < !std::is_same::type, json_pointer>::value&& @@ -3790,7 +3818,36 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } #if defined(JSON_HAS_CPP_17) - /// @copydoc operator[](KeyT&&) const + /*! + @brief read-only access specified object element + + Returns a const reference to the element at with specified key @a key. No + bounds checking is performed. + + @warning If the element with key @a key does not exist, the behavior is + undefined. + + @param[in] key key of the element to access + + @return const reference to the element at key @a key + + @pre The element with key @a key must exist. **This precondition is + enforced with an assertion.** + + @throw type_error.305 if the JSON value is not an object; in that case, + using the [] operator with a key makes no sense. + + @complexity Logarithmic in the size of the container. + + @liveexample{The example below shows how object elements can be read using + the `[]` operator.,operatorarray__key_type_const} + + @sa see @ref at(const typename object_t::key_type&) for access by reference + with range checking + @sa see @ref value() for access by value with a default value + + @since version 3.10.0 + */ const_reference operator[](const std::string_view& key) const { // operator[] only works for objects @@ -3922,6 +3979,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @param[in] key key of the element to access @param[in] default_value the value to return if @a key is not found + @tparam KeyType A type for an object key. This can also be a string + literal or a string view (C++17). @tparam ValueType type compatible to JSON values, for instance `int` for JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for JSON arrays. Note the type of the expected value at @a key and the default @@ -3945,7 +4004,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @sa see @ref operator[](const typename object_t::key_type&) for unchecked access by reference - @since version 1.0.0 + @since version 1.0.0, KeyType template added in 3.10.0 */ // using std::is_convertible in a std::enable_if will fail when using explicit conversions template < class KeyType, class ValueType, typename std::enable_if < @@ -4382,7 +4441,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec Removes elements from a JSON object with the key value @a key. @param[in] key value of the elements to remove - @tparam KeyT a type convertible to an object key or a `std::string_view` + @tparam KeyT a type convertible to an object key @return Number of elements removed. If @a ObjectType is the default `std::map` type, the return value will always be `0` (@a key was not @@ -4404,7 +4463,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @sa see @ref erase(const size_type) -- removes the element from an array at the given index - @since version 1.0.0 + @since version 1.0.0; template added in version 3.10.0 */ template < class KeyT, typename std::enable_if < #if defined(JSON_HAS_CPP_17) @@ -4423,6 +4482,35 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } #if defined(JSON_HAS_CPP_17) + /*! + @brief remove element from a JSON object given a key + + Removes elements from a JSON object with the key value @a key. + + @param[in] key value of the elements to remove + + @return Number of elements removed. If @a ObjectType is the default + `std::map` type, the return value will always be `0` (@a key was not + found) or `1` (@a key was found). + + @post References and iterators to the erased elements are invalidated. + Other references and iterators are not affected. + + @throw type_error.307 when called on a type other than JSON object; + example: `"cannot use erase() with null"` + + @complexity `log(size()) + count(key)` + + @liveexample{The example shows the effect of `erase()`.,erase__key_type} + + @sa see @ref erase(IteratorType) -- removes the element at a given position + @sa see @ref erase(IteratorType, IteratorType) -- removes the elements in + the given range + @sa see @ref erase(const size_type) -- removes the element from an array at + the given index + + @since version 3.10.0 + */ size_type erase(const std::string_view& key) { // this erase only works for objects diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 58552e2f7..84f53e98e 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -20376,7 +20376,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec access by reference @sa see @ref value() for access by value with a default value - @since version 1.0.0 + @since version 1.0.0; template added in version 3.10.0 @liveexample{The example below shows how object elements can be read and written using `at()`. It also demonstrates the different exceptions that @@ -20429,7 +20429,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec access by reference @sa see @ref value() for access by value with a default value - @since version 1.0.0 + @since version 1.0.0; template added in version 3.10.0 @liveexample{The example below shows how object elements can be read using `at()`. It also demonstrates the different exceptions that can be thrown., @@ -20556,7 +20556,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec In case the value was `null` before, it is converted to an object. @param[in] key key of the element to access - @tparam KeyT a type convertible to an object key, excluding `std::string_view` + @tparam KeyT a type convertible to an object key @return reference to the element at key @a key @@ -20572,7 +20572,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec with range checking @sa see @ref value() for access by value with a default value - @since version 1.0.0 + @since version 1.0.0; template added in version 3.10.0 */ template < class KeyT, typename std::enable_if < !std::is_same::type, json_pointer>::value&& @@ -20600,7 +20600,33 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } #if defined(JSON_HAS_CPP_17) - /// @copydoc operator[](KeyT&&) + /*! + @brief access specified object element + + Returns a reference to the element at with specified key @a key. + + @note If @a key is not found in the object, then it is silently added to + the object and filled with a `null` value to make `key` a valid reference. + In case the value was `null` before, it is converted to an object. + + @param[in] key key of the element to access + + @return reference to the element at key @a key + + @throw type_error.305 if the JSON value is not an object or null; in that + cases, using the [] operator with a key makes no sense. + + @complexity Logarithmic in the size of the container. + + @liveexample{The example below shows how object elements can be read and + written using the `[]` operator.,operatorarray__key_type} + + @sa see @ref at(const typename object_t::key_type&) for access by reference + with range checking + @sa see @ref value() for access by value with a default value + + @since version 3.10.0 + */ reference operator[](const std::string_view& key) { // implicitly convert null value to an empty object @@ -20638,7 +20664,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec undefined. @param[in] key key of the element to access - @tparam KeyT a type convertible to an object key or, excluding `std::string_view` + @tparam KeyT a type convertible to an object key or @return const reference to the element at key @a key @@ -20657,7 +20683,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec with range checking @sa see @ref value() for access by value with a default value - @since version 1.0.0 + @since version 1.0.0; template added in version 3.10.0 */ template < class KeyT, typename std::enable_if < !std::is_same::type, json_pointer>::value&& @@ -20679,7 +20705,36 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } #if defined(JSON_HAS_CPP_17) - /// @copydoc operator[](KeyT&&) const + /*! + @brief read-only access specified object element + + Returns a const reference to the element at with specified key @a key. No + bounds checking is performed. + + @warning If the element with key @a key does not exist, the behavior is + undefined. + + @param[in] key key of the element to access + + @return const reference to the element at key @a key + + @pre The element with key @a key must exist. **This precondition is + enforced with an assertion.** + + @throw type_error.305 if the JSON value is not an object; in that case, + using the [] operator with a key makes no sense. + + @complexity Logarithmic in the size of the container. + + @liveexample{The example below shows how object elements can be read using + the `[]` operator.,operatorarray__key_type_const} + + @sa see @ref at(const typename object_t::key_type&) for access by reference + with range checking + @sa see @ref value() for access by value with a default value + + @since version 3.10.0 + */ const_reference operator[](const std::string_view& key) const { // operator[] only works for objects @@ -20811,6 +20866,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @param[in] key key of the element to access @param[in] default_value the value to return if @a key is not found + @tparam KeyType A type for an object key. This can also be a string + literal or a string view (C++17). @tparam ValueType type compatible to JSON values, for instance `int` for JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for JSON arrays. Note the type of the expected value at @a key and the default @@ -20834,7 +20891,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @sa see @ref operator[](const typename object_t::key_type&) for unchecked access by reference - @since version 1.0.0 + @since version 1.0.0, KeyType template added in 3.10.0 */ // using std::is_convertible in a std::enable_if will fail when using explicit conversions template < class KeyType, class ValueType, typename std::enable_if < @@ -20844,7 +20901,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec std::is_same::value || #endif std::is_convertible::value), int >::type = 0 > - ValueType value(const KeyType& key, const ValueType& default_value) const + ValueType value(KeyType && key, const ValueType& default_value) const { // at only works for objects if (JSON_HEDLEY_LIKELY(is_object())) @@ -21271,7 +21328,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec Removes elements from a JSON object with the key value @a key. @param[in] key value of the elements to remove - @tparam KeyT a type convertible to an object key or a `std::string_view` + @tparam KeyT a type convertible to an object key @return Number of elements removed. If @a ObjectType is the default `std::map` type, the return value will always be `0` (@a key was not @@ -21293,7 +21350,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @sa see @ref erase(const size_type) -- removes the element from an array at the given index - @since version 1.0.0 + @since version 1.0.0; template added in version 3.10.0 */ template < class KeyT, typename std::enable_if < #if defined(JSON_HAS_CPP_17) @@ -21312,6 +21369,35 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } #if defined(JSON_HAS_CPP_17) + /*! + @brief remove element from a JSON object given a key + + Removes elements from a JSON object with the key value @a key. + + @param[in] key value of the elements to remove + + @return Number of elements removed. If @a ObjectType is the default + `std::map` type, the return value will always be `0` (@a key was not + found) or `1` (@a key was found). + + @post References and iterators to the erased elements are invalidated. + Other references and iterators are not affected. + + @throw type_error.307 when called on a type other than JSON object; + example: `"cannot use erase() with null"` + + @complexity `log(size()) + count(key)` + + @liveexample{The example shows the effect of `erase()`.,erase__key_type} + + @sa see @ref erase(IteratorType) -- removes the element at a given position + @sa see @ref erase(IteratorType, IteratorType) -- removes the elements in + the given range + @sa see @ref erase(const size_type) -- removes the element from an array at + the given index + + @since version 3.10.0 + */ size_type erase(const std::string_view& key) { // this erase only works for objects diff --git a/test/src/unit-element_access2.cpp b/test/src/unit-element_access2.cpp index 43f879a7a..69e3a1883 100644 --- a/test/src/unit-element_access2.cpp +++ b/test/src/unit-element_access2.cpp @@ -608,6 +608,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