diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp
index 409a6e79..15921726 100644
--- a/include/nlohmann/json.hpp
+++ b/include/nlohmann/json.hpp
@@ -72,6 +72,7 @@ SOFTWARE.
 #include <nlohmann/detail/output/serializer.hpp>
 #include <nlohmann/detail/value_t.hpp>
 #include <nlohmann/json_fwd.hpp>
+#include <nlohmann/ordered_map.hpp>
 
 /*!
 @brief namespace for Niels Lohmann
diff --git a/include/nlohmann/json_fwd.hpp b/include/nlohmann/json_fwd.hpp
index 824e86a1..d9e5428d 100644
--- a/include/nlohmann/json_fwd.hpp
+++ b/include/nlohmann/json_fwd.hpp
@@ -60,6 +60,19 @@ uses the standard template types.
 @since version 1.0.0
 */
 using json = basic_json<>;
+
+template<class Key, class T, class IgnoredLess, class Allocator, class Container>
+struct ordered_map;
+
+/*!
+@brief ordered JSON class
+
+This type preserves the insertion order of object keys.
+
+@since version 3.9.0
+*/
+using ordered_json = basic_json<nlohmann::ordered_map>;
+
 }  // namespace nlohmann
 
 #endif  // INCLUDE_NLOHMANN_JSON_FWD_HPP_
diff --git a/include/nlohmann/ordered_map.hpp b/include/nlohmann/ordered_map.hpp
new file mode 100644
index 00000000..744541f3
--- /dev/null
+++ b/include/nlohmann/ordered_map.hpp
@@ -0,0 +1,62 @@
+#pragma once
+
+#include <functional> // less
+#include <memory> // allocator
+#include <utility> // pair
+#include <vector> // vector
+
+namespace nlohmann
+{
+
+/// ordered_map: a minimal map-like container that preserves insertion order
+/// for use within nlohmann::basic_json<ordered_map>
+template<class Key, class T, class IgnoredLess = std::less<Key>,
+         class Allocator = std::allocator<std::pair<const Key, T>>,
+         class Container = std::vector<std::pair<const Key, T>, Allocator>>
+struct ordered_map : Container
+{
+    using key_type = Key;
+    using mapped_type = T;
+    using value_type = std::pair<const Key, T>;
+    using Container::Container;
+
+    std::pair<typename Container::iterator, bool> emplace(key_type&& key, T&& t)
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (it->first == key)
+            {
+                return {it, false};
+            }
+        }
+
+        this->emplace_back(key, t);
+        return {--this->end(), true};
+    }
+
+    std::size_t erase(const key_type& key)
+    {
+        std::size_t result = 0;
+        for (auto it = this->begin(); it != this->end();)
+        {
+            if (it->first == key)
+            {
+                ++result;
+                it = Container::erase(it);
+            }
+            else
+            {
+                ++it;
+            }
+        }
+
+        return result;
+    }
+
+    T& operator[](key_type&& key)
+    {
+        return emplace(std::move(key), T{}).first->second;
+    }
+};
+
+}  // namespace nlohmann
diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp
index cc822a54..f7f1664e 100644
--- a/single_include/nlohmann/json.hpp
+++ b/single_include/nlohmann/json.hpp
@@ -2772,6 +2772,15 @@ uses the standard template types.
 @since version 1.0.0
 */
 using json = basic_json<>;
+
+template<class Key, class T, class IgnoredLess, class Allocator, class Container>
+struct ordered_map;
+
+/*!
+@since version 3.9.0
+*/
+using ordered_json = basic_json<nlohmann::ordered_map>;
+
 }  // namespace nlohmann
 
 #endif  // INCLUDE_NLOHMANN_JSON_FWD_HPP_
@@ -15853,6 +15862,70 @@ class serializer
 
 // #include <nlohmann/json_fwd.hpp>
 
+// #include <nlohmann/ordered_map.hpp>
+
+
+#include <functional> // less
+#include <memory> // allocator
+#include <utility> // pair
+#include <vector> // vector
+
+namespace nlohmann
+{
+
+/// ordered_map: a minimal map-like container that preserves insertion order
+/// for use within nlohmann::basic_json<ordered_map>
+template<class Key, class T, class IgnoredLess = std::less<Key>,
+         class Allocator = std::allocator<std::pair<const Key, T>>,
+         class Container = std::vector<std::pair<const Key, T>, Allocator>>
+struct ordered_map : Container
+{
+    using key_type = Key;
+    using mapped_type = T;
+    using value_type = std::pair<const Key, T>;
+    using Container::Container;
+
+    std::pair<typename Container::iterator, bool> emplace(Key&& key, T&& t)
+    {
+        for (auto it = this->begin(); it != this->end(); ++it)
+        {
+            if (it->first == key)
+            {
+                return {it, false};
+            }
+        }
+
+        this->emplace_back(key, t);
+        return {--this->end(), true};
+    }
+
+    std::size_t erase(const Key& key)
+    {
+        std::size_t result = 0;
+        for (auto it = this->begin(); it != this->end(); )
+        {
+            if (it->first == key)
+            {
+                ++result;
+                it = Container::erase(it);
+            }
+            else
+            {
+                ++it;
+            }
+        }
+
+        return result;
+    }
+
+    T& operator[]( Key&& key )
+    {
+        return emplace(std::move(key), T{}).first->second;
+    }
+};
+
+}  // namespace nlohmann
+
 
 /*!
 @brief namespace for Niels Lohmann
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index fdf5ac5b..8e663f49 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -123,6 +123,7 @@ set(files
     src/unit-modifiers.cpp
     src/unit-msgpack.cpp
     src/unit-noexcept.cpp
+    src/unit-ordered_json.cpp
     src/unit-pointer_access.cpp
     src/unit-readme.cpp
     src/unit-reference_access.cpp
diff --git a/test/src/unit-ordered_json.cpp b/test/src/unit-ordered_json.cpp
new file mode 100644
index 00000000..1a97ece6
--- /dev/null
+++ b/test/src/unit-ordered_json.cpp
@@ -0,0 +1,61 @@
+/*
+    __ _____ _____ _____
+ __|  |   __|     |   | |  JSON for Modern C++ (test suite)
+|  |  |__   |  |  | | | |  version 3.8.0
+|_____|_____|_____|_|___|  https://github.com/nlohmann/json
+
+Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
+Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
+
+Permission is hereby  granted, free of charge, to any  person obtaining a copy
+of this software and associated  documentation files (the "Software"), to deal
+in the Software  without restriction, including without  limitation the rights
+to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
+copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
+IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
+FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
+AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
+LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#include "doctest_compatibility.h"
+
+#include <nlohmann/json.hpp>
+using nlohmann::json;
+using nlohmann::ordered_json;
+
+
+TEST_CASE("ordered_json")
+{
+    json j;
+    ordered_json oj;
+
+    j["element3"] = 3;
+    j["element1"] = 1;
+    j["element2"] = 2;
+
+    oj["element3"] = 3;
+    oj["element1"] = 1;
+    oj["element2"] = 2;
+
+    CHECK(j.dump() == "{\"element1\":1,\"element2\":2,\"element3\":3}");
+    CHECK(oj.dump() == "{\"element3\":3,\"element1\":1,\"element2\":2}");
+
+    CHECK(j == json(oj));
+    CHECK(ordered_json(json(oj)) == ordered_json(j));
+
+    j.erase("element1");
+    oj.erase("element1");
+
+    CHECK(j.dump() == "{\"element2\":2,\"element3\":3}");
+    CHECK(oj.dump() == "{\"element3\":3,\"element2\":2}");
+}