From 6a5db0095199a5b1173061e0c9477bddb1a8d788 Mon Sep 17 00:00:00 2001
From: Isaac Nickaein <nickaein.i@gmail.com>
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<KeyT>(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<typename KeyT>
+    bool contains(KeyT&& key) const
+    {
+        if (is_object())
+        {
+            return (m_value.object->find(std::forward<KeyT>(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<KeyT>(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<typename KeyT>
+    bool contains(KeyT&& key) const
+    {
+        if (is_object())
+        {
+            return (m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end());
+        }
+        else
+        {
+            return false;
+        }
+    }
+
     /// @}
 
 

From e93f3054940348e2aca777629cd3cf3f0cf3cfdf Mon Sep 17 00:00:00 2001
From: Isaac Nickaein <nickaein.i@gmail.com>
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);
+                }
+            }
+        }
     }
 }