diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 9208f63cf..3554be127 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -3957,6 +3957,39 @@ class basic_json return is_object() ? m_value.object->count(std::forward(key)) : 0; } + /*! + @brief check the existence of an element in a JSON object + + Check whether an element exists in a JSON object with key equivalent to + @a key. If the element is not found or the JSON value is not an object, + false is returned. + + @note This method always returns false when executed on a JSON type + that is not an object. + + @param[in] key key value to check its existence. + + @return true if an element with specified @a key exists. If no such + element with such key is found or the JSON value is not an object, + false is returned. + + @complexity Logarithmic in the size of the JSON object. + + @since version 3.6.0 + */ + template + bool contains(KeyT&& key) const + { + if (is_object()) + { + return (m_value.object->find(std::forward(key)) != m_value.object->end()); + } + else + { + return false; + } + } + /// @} diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 892b96885..1b83be0b3 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -16465,6 +16465,39 @@ class basic_json return is_object() ? m_value.object->count(std::forward(key)) : 0; } + /*! + @brief check the existence of an element in a JSON object + + Check whether an element exists in a JSON object with key equivalent to + @a key. If the element is not found or the JSON value is not an object, + false is returned. + + @note This method always returns false when executed on a JSON type + that is not an object. + + @param[in] key key value to check its existence. + + @return true if an element with specified @a key exists. If no such + element with such key is found or the JSON value is not an object, + false is returned. + + @complexity Logarithmic in the size of the JSON object. + + @since version 3.6.0 + */ + template + bool contains(KeyT&& key) const + { + if (is_object()) + { + return (m_value.object->find(std::forward(key)) != m_value.object->end()); + } + else + { + return false; + } + } + /// @} diff --git a/test/src/unit-element_access2.cpp b/test/src/unit-element_access2.cpp index 52a30073d..2dc8ef941 100644 --- a/test/src/unit-element_access2.cpp +++ b/test/src/unit-element_access2.cpp @@ -982,6 +982,93 @@ TEST_CASE("element access 2") } } } + + SECTION("check existence of key in an object") + { + SECTION("existing element") + { + for (auto key : + {"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array" + }) + { + CHECK(j.contains(key) == true); + CHECK(j_const.contains(key) == true); + } + } + + SECTION("nonexisting element") + { + CHECK(j.contains("foo") == false); + CHECK(j_const.contains("foo") == false); + } + + SECTION("all types") + { + SECTION("null") + { + json j_nonobject(json::value_t::null); + const json j_nonobject_const(j_nonobject); + CHECK(j_nonobject.contains("foo") == false); + CHECK(j_nonobject_const.contains("foo") == false); + } + + SECTION("string") + { + json j_nonobject(json::value_t::string); + const json j_nonobject_const(j_nonobject); + CHECK(j_nonobject.contains("foo") == false); + CHECK(j_nonobject_const.contains("foo") == false); + } + + SECTION("object") + { + json j_nonobject(json::value_t::object); + const json j_nonobject_const(j_nonobject); + CHECK(j_nonobject.contains("foo") == false); + CHECK(j_nonobject_const.contains("foo") == false); + } + + SECTION("array") + { + json j_nonobject(json::value_t::array); + const json j_nonobject_const(j_nonobject); + CHECK(j_nonobject.contains("foo") == false); + CHECK(j_nonobject_const.contains("foo") == false); + } + + SECTION("boolean") + { + json j_nonobject(json::value_t::boolean); + const json j_nonobject_const(j_nonobject); + CHECK(j_nonobject.contains("foo") == false); + CHECK(j_nonobject_const.contains("foo") == false); + } + + SECTION("number (integer)") + { + json j_nonobject(json::value_t::number_integer); + const json j_nonobject_const(j_nonobject); + CHECK(j_nonobject.contains("foo") == false); + CHECK(j_nonobject_const.contains("foo") == false); + } + + SECTION("number (unsigned)") + { + json j_nonobject(json::value_t::number_unsigned); + const json j_nonobject_const(j_nonobject); + CHECK(j_nonobject.contains("foo") == false); + CHECK(j_nonobject_const.contains("foo") == false); + } + + SECTION("number (floating-point)") + { + json j_nonobject(json::value_t::number_float); + const json j_nonobject_const(j_nonobject); + CHECK(j_nonobject.contains("foo") == false); + CHECK(j_nonobject_const.contains("foo") == false); + } + } + } } }