diff --git a/doc/examples/items.cpp b/doc/examples/items.cpp
new file mode 100644
index 00000000..b2224d60
--- /dev/null
+++ b/doc/examples/items.cpp
@@ -0,0 +1,23 @@
+#include <iostream>
+#include "json.hpp"
+
+using json = nlohmann::json;
+
+int main()
+{
+    // create JSON values
+    json j_object = {{"one", 1}, {"two", 2}};
+    json j_array = {1, 2, 4, 8, 16};
+
+    // example for an object
+    for (auto& x : j_object.items())
+    {
+        std::cout << "key: " << x.key() << ", value: " << x.value() << '\n';
+    }
+
+    // example for an array
+    for (auto& x : j_array.items())
+    {
+        std::cout << "key: " << x.key() << ", value: " << x.value() << '\n';
+    }
+}
diff --git a/doc/examples/items.link b/doc/examples/items.link
new file mode 100644
index 00000000..0b74c5b3
--- /dev/null
+++ b/doc/examples/items.link
@@ -0,0 +1 @@
+<a target="_blank" href="https://wandbox.org/permlink/E7h0HOuw778Ski8S"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/items.output b/doc/examples/items.output
new file mode 100644
index 00000000..89b09f52
--- /dev/null
+++ b/doc/examples/items.output
@@ -0,0 +1,7 @@
+key: one, value: 1
+key: two, value: 2
+key: 0, value: 1
+key: 1, value: 2
+key: 2, value: 4
+key: 3, value: 8
+key: 4, value: 16
diff --git a/src/json.hpp b/src/json.hpp
index 5b0b0ea5..a12fcbe3 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -11375,6 +11375,68 @@ class basic_json
         return iteration_proxy<const_iterator>(ref);
     }
 
+    /*!
+    @brief helper to access iterator member functions in range-based for
+
+    This function allows to access @ref iterator::key() and @ref
+    iterator::value() during range-based for loops. In these loops, a
+    reference to the JSON values is returned, so there is no access to the
+    underlying iterator.
+
+    For loop without `items()` function:
+
+    @code{cpp}
+    for (auto it = j_object.begin(); it != j_object.end(); ++it)
+    {
+        std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
+    }
+    @endcode
+
+    Range-based for loop without `items()` function:
+
+    @code{cpp}
+    for (auto it : j_object)
+    {
+        // "it" is of type json::reference and has no key() member
+        std::cout << "value: " << it << '\n';
+    }
+    @endcode
+
+    Range-based for loop with `items()` function:
+
+    @code{cpp}
+    for (auto it : j_object.items())
+    {
+        std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
+    }
+    @endcode
+
+    @note When iterating over an array, `key()` will return the index of the
+          element as string (see example).
+
+    @return iteration proxy object wrapping @a ref with an interface to use in
+            range-based for loops
+
+    @liveexample{The following code shows how the function is used.,items}
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes in the JSON value.
+
+    @complexity Constant.
+    */
+    iteration_proxy<iterator> items()
+    {
+        return iteration_proxy<iterator>(*this);
+    }
+
+    /*!
+    @copydoc items()
+    */
+    iteration_proxy<const_iterator> items() const
+    {
+        return iteration_proxy<const_iterator>(*this);
+    }
+
     /// @}
 
 
diff --git a/test/src/unit-iterator_wrapper.cpp b/test/src/unit-iterator_wrapper.cpp
index e16ce16d..4f5bd15d 100644
--- a/test/src/unit-iterator_wrapper.cpp
+++ b/test/src/unit-iterator_wrapper.cpp
@@ -727,3 +727,700 @@ TEST_CASE("iterator_wrapper")
         }
     }
 }
+
+TEST_CASE("items()")
+{
+    SECTION("object")
+    {
+        SECTION("value")
+        {
+            json j = {{"A", 1}, {"B", 2}};
+            int counter = 1;
+
+            for (auto i : j.items())
+            {
+                switch (counter++)
+                {
+                    case 1:
+                    {
+                        CHECK(i.key() == "A");
+                        CHECK(i.value() == json(1));
+                        break;
+                    }
+
+                    case 2:
+                    {
+                        CHECK(i.key() == "B");
+                        CHECK(i.value() == json(2));
+                        break;
+                    }
+
+                    default:
+                    {
+                        break;
+                    }
+                }
+            }
+
+            CHECK(counter == 3);
+        }
+
+        SECTION("reference")
+        {
+            json j = {{"A", 1}, {"B", 2}};
+            int counter = 1;
+
+            for (auto& i : j.items())
+            {
+                switch (counter++)
+                {
+                    case 1:
+                    {
+                        CHECK(i.key() == "A");
+                        CHECK(i.value() == json(1));
+
+                        // change the value
+                        i.value() = json(11);
+                        CHECK(i.value() == json(11));
+                        break;
+                    }
+
+                    case 2:
+                    {
+                        CHECK(i.key() == "B");
+                        CHECK(i.value() == json(2));
+
+                        // change the value
+                        i.value() = json(22);
+                        CHECK(i.value() == json(22));
+                        break;
+                    }
+
+                    default:
+                    {
+                        break;
+                    }
+                }
+            }
+
+            CHECK(counter == 3);
+
+            // check if values where changed
+            CHECK(j == json({{"A", 11}, {"B", 22}}));
+        }
+
+        SECTION("const value")
+        {
+            json j = {{"A", 1}, {"B", 2}};
+            int counter = 1;
+
+            for (const auto i : j.items())
+            {
+                switch (counter++)
+                {
+                    case 1:
+                    {
+                        CHECK(i.key() == "A");
+                        CHECK(i.value() == json(1));
+                        break;
+                    }
+
+                    case 2:
+                    {
+                        CHECK(i.key() == "B");
+                        CHECK(i.value() == json(2));
+                        break;
+                    }
+
+                    default:
+                    {
+                        break;
+                    }
+                }
+            }
+
+            CHECK(counter == 3);
+        }
+
+        SECTION("const reference")
+        {
+            json j = {{"A", 1}, {"B", 2}};
+            int counter = 1;
+
+            for (const auto& i : j.items())
+            {
+                switch (counter++)
+                {
+                    case 1:
+                    {
+                        CHECK(i.key() == "A");
+                        CHECK(i.value() == json(1));
+                        break;
+                    }
+
+                    case 2:
+                    {
+                        CHECK(i.key() == "B");
+                        CHECK(i.value() == json(2));
+                        break;
+                    }
+
+                    default:
+                    {
+                        break;
+                    }
+                }
+            }
+
+            CHECK(counter == 3);
+        }
+    }
+
+    SECTION("const object")
+    {
+        SECTION("value")
+        {
+            const json j = {{"A", 1}, {"B", 2}};
+            int counter = 1;
+
+            for (auto i : j.items())
+            {
+                switch (counter++)
+                {
+                    case 1:
+                    {
+                        CHECK(i.key() == "A");
+                        CHECK(i.value() == json(1));
+                        break;
+                    }
+
+                    case 2:
+                    {
+                        CHECK(i.key() == "B");
+                        CHECK(i.value() == json(2));
+                        break;
+                    }
+
+                    default:
+                    {
+                        break;
+                    }
+                }
+            }
+
+            CHECK(counter == 3);
+        }
+
+        SECTION("reference")
+        {
+            const json j = {{"A", 1}, {"B", 2}};
+            int counter = 1;
+
+            for (auto& i : j.items())
+            {
+                switch (counter++)
+                {
+                    case 1:
+                    {
+                        CHECK(i.key() == "A");
+                        CHECK(i.value() == json(1));
+                        break;
+                    }
+
+                    case 2:
+                    {
+                        CHECK(i.key() == "B");
+                        CHECK(i.value() == json(2));
+                        break;
+                    }
+
+                    default:
+                    {
+                        break;
+                    }
+                }
+            }
+
+            CHECK(counter == 3);
+        }
+
+        SECTION("const value")
+        {
+            const json j = {{"A", 1}, {"B", 2}};
+            int counter = 1;
+
+            for (const auto i : j.items())
+            {
+                switch (counter++)
+                {
+                    case 1:
+                    {
+                        CHECK(i.key() == "A");
+                        CHECK(i.value() == json(1));
+                        break;
+                    }
+
+                    case 2:
+                    {
+                        CHECK(i.key() == "B");
+                        CHECK(i.value() == json(2));
+                        break;
+                    }
+
+                    default:
+                    {
+                        break;
+                    }
+                }
+            }
+
+            CHECK(counter == 3);
+        }
+
+        SECTION("const reference")
+        {
+            const json j = {{"A", 1}, {"B", 2}};
+            int counter = 1;
+
+            for (const auto& i : j.items())
+            {
+                switch (counter++)
+                {
+                    case 1:
+                    {
+                        CHECK(i.key() == "A");
+                        CHECK(i.value() == json(1));
+                        break;
+                    }
+
+                    case 2:
+                    {
+                        CHECK(i.key() == "B");
+                        CHECK(i.value() == json(2));
+                        break;
+                    }
+
+                    default:
+                    {
+                        break;
+                    }
+                }
+            }
+
+            CHECK(counter == 3);
+        }
+    }
+
+    SECTION("array")
+    {
+        SECTION("value")
+        {
+            json j = {"A", "B"};
+            int counter = 1;
+
+            for (auto i : j.items())
+            {
+                switch (counter++)
+                {
+                    case 1:
+                    {
+                        CHECK(i.key() == "0");
+                        CHECK(i.value() == "A");
+                        break;
+                    }
+
+                    case 2:
+                    {
+                        CHECK(i.key() == "1");
+                        CHECK(i.value() == "B");
+                        break;
+                    }
+
+                    default:
+                    {
+                        break;
+                    }
+                }
+            }
+
+            CHECK(counter == 3);
+        }
+
+        SECTION("reference")
+        {
+            json j = {"A", "B"};
+            int counter = 1;
+
+            for (auto& i : j.items())
+            {
+                switch (counter++)
+                {
+                    case 1:
+                    {
+                        CHECK(i.key() == "0");
+                        CHECK(i.value() == "A");
+
+                        // change the value
+                        i.value() = "AA";
+                        CHECK(i.value() == "AA");
+                        break;
+                    }
+
+                    case 2:
+                    {
+                        CHECK(i.key() == "1");
+                        CHECK(i.value() == "B");
+
+                        // change the value
+                        i.value() = "BB";
+                        CHECK(i.value() == "BB");
+                        break;
+                    }
+
+                    default:
+                    {
+                        break;
+                    }
+                }
+            }
+
+            CHECK(counter == 3);
+
+            // check if values where changed
+            CHECK(j == json({"AA", "BB"}));
+        }
+
+        SECTION("const value")
+        {
+            json j = {"A", "B"};
+            int counter = 1;
+
+            for (const auto i : j.items())
+            {
+                switch (counter++)
+                {
+                    case 1:
+                    {
+                        CHECK(i.key() == "0");
+                        CHECK(i.value() == "A");
+                        break;
+                    }
+
+                    case 2:
+                    {
+                        CHECK(i.key() == "1");
+                        CHECK(i.value() == "B");
+                        break;
+                    }
+
+                    default:
+                    {
+                        break;
+                    }
+                }
+            }
+
+            CHECK(counter == 3);
+        }
+
+        SECTION("const reference")
+        {
+            json j = {"A", "B"};
+            int counter = 1;
+
+            for (const auto& i : j.items())
+            {
+                switch (counter++)
+                {
+                    case 1:
+                    {
+                        CHECK(i.key() == "0");
+                        CHECK(i.value() == "A");
+                        break;
+                    }
+
+                    case 2:
+                    {
+                        CHECK(i.key() == "1");
+                        CHECK(i.value() == "B");
+                        break;
+                    }
+
+                    default:
+                    {
+                        break;
+                    }
+                }
+            }
+
+            CHECK(counter == 3);
+        }
+    }
+
+    SECTION("const array")
+    {
+        SECTION("value")
+        {
+            const json j = {"A", "B"};
+            int counter = 1;
+
+            for (auto i : j.items())
+            {
+                switch (counter++)
+                {
+                    case 1:
+                    {
+                        CHECK(i.key() == "0");
+                        CHECK(i.value() == "A");
+                        break;
+                    }
+
+                    case 2:
+                    {
+                        CHECK(i.key() == "1");
+                        CHECK(i.value() == "B");
+                        break;
+                    }
+
+                    default:
+                    {
+                        break;
+                    }
+                }
+            }
+
+            CHECK(counter == 3);
+        }
+
+        SECTION("reference")
+        {
+            const json j = {"A", "B"};
+            int counter = 1;
+
+            for (auto& i : j.items())
+            {
+                switch (counter++)
+                {
+                    case 1:
+                    {
+                        CHECK(i.key() == "0");
+                        CHECK(i.value() == "A");
+                        break;
+                    }
+
+                    case 2:
+                    {
+                        CHECK(i.key() == "1");
+                        CHECK(i.value() == "B");
+                        break;
+                    }
+
+                    default:
+                    {
+                        break;
+                    }
+                }
+            }
+
+            CHECK(counter == 3);
+        }
+
+        SECTION("const value")
+        {
+            const json j = {"A", "B"};
+            int counter = 1;
+
+            for (const auto i : j.items())
+            {
+                switch (counter++)
+                {
+                    case 1:
+                    {
+                        CHECK(i.key() == "0");
+                        CHECK(i.value() == "A");
+                        break;
+                    }
+
+                    case 2:
+                    {
+                        CHECK(i.key() == "1");
+                        CHECK(i.value() == "B");
+                        break;
+                    }
+
+                    default:
+                    {
+                        break;
+                    }
+                }
+            }
+
+            CHECK(counter == 3);
+        }
+
+        SECTION("const reference")
+        {
+            const json j = {"A", "B"};
+            int counter = 1;
+
+            for (const auto& i : j.items())
+            {
+                switch (counter++)
+                {
+                    case 1:
+                    {
+                        CHECK(i.key() == "0");
+                        CHECK(i.value() == "A");
+                        break;
+                    }
+
+                    case 2:
+                    {
+                        CHECK(i.key() == "1");
+                        CHECK(i.value() == "B");
+                        break;
+                    }
+
+                    default:
+                    {
+                        break;
+                    }
+                }
+            }
+
+            CHECK(counter == 3);
+        }
+    }
+
+    SECTION("primitive")
+    {
+        SECTION("value")
+        {
+            json j = 1;
+            int counter = 1;
+
+            for (auto i : j.items())
+            {
+                ++counter;
+                CHECK(i.key() == "");
+                CHECK(i.value() == json(1));
+            }
+
+            CHECK(counter == 2);
+        }
+
+        SECTION("reference")
+        {
+            json j = 1;
+            int counter = 1;
+
+            for (auto& i : j.items())
+            {
+                ++counter;
+                CHECK(i.key() == "");
+                CHECK(i.value() == json(1));
+
+                // change value
+                i.value() = json(2);
+            }
+
+            CHECK(counter == 2);
+
+            // check if value has changed
+            CHECK(j == json(2));
+        }
+
+        SECTION("const value")
+        {
+            json j = 1;
+            int counter = 1;
+
+            for (const auto i : j.items())
+            {
+                ++counter;
+                CHECK(i.key() == "");
+                CHECK(i.value() == json(1));
+            }
+
+            CHECK(counter == 2);
+        }
+
+        SECTION("const reference")
+        {
+            json j = 1;
+            int counter = 1;
+
+            for (const auto& i : j.items())
+            {
+                ++counter;
+                CHECK(i.key() == "");
+                CHECK(i.value() == json(1));
+            }
+
+            CHECK(counter == 2);
+        }
+    }
+
+    SECTION("const primitive")
+    {
+        SECTION("value")
+        {
+            const json j = 1;
+            int counter = 1;
+
+            for (auto i : j.items())
+            {
+                ++counter;
+                CHECK(i.key() == "");
+                CHECK(i.value() == json(1));
+            }
+
+            CHECK(counter == 2);
+        }
+
+        SECTION("reference")
+        {
+            const json j = 1;
+            int counter = 1;
+
+            for (auto& i : j.items())
+            {
+                ++counter;
+                CHECK(i.key() == "");
+                CHECK(i.value() == json(1));
+            }
+
+            CHECK(counter == 2);
+        }
+
+        SECTION("const value")
+        {
+            const json j = 1;
+            int counter = 1;
+
+            for (const auto i : j.items())
+            {
+                ++counter;
+                CHECK(i.key() == "");
+                CHECK(i.value() == json(1));
+            }
+
+            CHECK(counter == 2);
+        }
+
+        SECTION("const reference")
+        {
+            const json j = 1;
+            int counter = 1;
+
+            for (const auto& i : j.items())
+            {
+                ++counter;
+                CHECK(i.key() == "");
+                CHECK(i.value() == json(1));
+            }
+
+            CHECK(counter == 2);
+        }
+    }
+}