From 6a5db0095199a5b1173061e0c9477bddb1a8d788 Mon Sep 17 00:00:00 2001 From: Isaac Nickaein Date: Sun, 10 Feb 2019 16:40:30 +0330 Subject: [PATCH 1/2] Implement contains() to check existence of a key --- include/nlohmann/json.hpp | 33 ++++++++++++++++++++++++++++++++ single_include/nlohmann/json.hpp | 33 ++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index d13f8a9e..834210d8 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 ee72531b..aac3b16c 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -16456,6 +16456,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; + } + } + /// @} From e93f3054940348e2aca777629cd3cf3f0cf3cfdf Mon Sep 17 00:00:00 2001 From: Isaac Nickaein Date: Sun, 10 Feb 2019 16:42:01 +0330 Subject: [PATCH 2/2] Add unit-test for contains() member function --- test/src/unit-element_access2.cpp | 87 +++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/test/src/unit-element_access2.cpp b/test/src/unit-element_access2.cpp index 52a30073..2dc8ef94 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); + } + } + } } }