diff --git a/doc/examples/emplace.cpp b/doc/examples/emplace.cpp
new file mode 100644
index 00000000..6014a361
--- /dev/null
+++ b/doc/examples/emplace.cpp
@@ -0,0 +1,23 @@
+#include <json.hpp>
+
+using json = nlohmann::json;
+
+int main()
+{
+    // create JSON values
+    json object = {{"one", 1}, {"two", 2}};
+    json null;
+
+    // print values
+    std::cout << object << '\n';
+    std::cout << null << '\n';
+
+    // add values
+    object.emplace("three", 3);
+    null.emplace("A", "a");
+    null.emplace("B", "b");
+
+    // print values
+    std::cout << object << '\n';
+    std::cout << null << '\n';
+}
diff --git a/doc/examples/emplace.link b/doc/examples/emplace.link
new file mode 100644
index 00000000..e78fd0e5
--- /dev/null
+++ b/doc/examples/emplace.link
@@ -0,0 +1 @@
+<a target="_blank" href="http://melpon.org/wandbox/permlink/Qg5Ogrh8yFrwT2GY"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/emplace.output b/doc/examples/emplace.output
new file mode 100644
index 00000000..2bc9c002
--- /dev/null
+++ b/doc/examples/emplace.output
@@ -0,0 +1,4 @@
+{"one":1,"two":2}
+null
+{"one":1,"three":3,"two":2}
+{"A":"a","B":"b"}
diff --git a/doc/examples/emplace_back.cpp b/doc/examples/emplace_back.cpp
new file mode 100644
index 00000000..4e9ec89a
--- /dev/null
+++ b/doc/examples/emplace_back.cpp
@@ -0,0 +1,23 @@
+#include <json.hpp>
+
+using json = nlohmann::json;
+
+int main()
+{
+    // create JSON values
+    json array = {1, 2, 3, 4, 5};
+    json null;
+
+    // print values
+    std::cout << array << '\n';
+    std::cout << null << '\n';
+
+    // add values
+    array.emplace_back(6);
+    null.emplace_back("first");
+    null.emplace_back(3, "second");
+
+    // print values
+    std::cout << array << '\n';
+    std::cout << null << '\n';
+}
diff --git a/doc/examples/emplace_back.link b/doc/examples/emplace_back.link
new file mode 100644
index 00000000..4363e4c7
--- /dev/null
+++ b/doc/examples/emplace_back.link
@@ -0,0 +1 @@
+<a target="_blank" href="http://melpon.org/wandbox/permlink/jdch45YEMX94DvlH"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/emplace_back.output b/doc/examples/emplace_back.output
new file mode 100644
index 00000000..bdd80d82
--- /dev/null
+++ b/doc/examples/emplace_back.output
@@ -0,0 +1,4 @@
+[1,2,3,4,5]
+null
+[1,2,3,4,5,6]
+["first",["second","second","second"]]
diff --git a/doc/index.md b/doc/index.md
index fcb5b432..70161d0e 100644
--- a/doc/index.md
+++ b/doc/index.md
@@ -197,7 +197,7 @@ The container functions known from STL have been extended to support the differe
     <td class="ok_green">@link nlohmann::basic_json::max_size `max_size` @endlink (returns `0`)</td>
   </tr>
   <tr>
-    <td rowspan="5">modifiers</td>
+    <td rowspan="6">modifiers</td>
     <td>`clear`</td>
     <td class="ok_green">@link nlohmann::basic_json::clear `clear` @endlink</td>
     <td class="ok_green">@link nlohmann::basic_json::clear `clear` @endlink</td>
@@ -233,6 +233,15 @@ The container functions known from STL have been extended to support the differe
     <td class="nok_throws">throws `std::domain_error`</td>
     <td class="ok_green">@link nlohmann::basic_json::push_back(const typename object_t::value_type & val) `push_back` @endlink (creates object)<br>@link nlohmann::basic_json::push_back(const nlohmann::basic_json &) `push_back` @endlink (creates array)</td>
   </tr>
+  <tr>
+    <td>`emplace` / `emplace_back`</td>
+    <td class="ok_green">@link nlohmann::basic_json::emplace() `emplace` @endlink</td>
+    <td class="ok_green">@link nlohmann::basic_json::emplace_back() `emplace_back` @endlink</td>
+    <td class="nok_throws">throws `std::domain_error`</td>
+    <td class="nok_throws">throws `std::domain_error`</td>
+    <td class="nok_throws">throws `std::domain_error`</td>
+    <td class="ok_green">@link nlohmann::basic_json::emplace() `emplace` @endlink (creates object)<br>@link nlohmann::basic_json::emplace_back() `emplace_back` @endlink (creates array)</td>
+  </tr>
   <tr>
     <td>`swap`</td>
     <td class="ok_green">@link nlohmann::basic_json::swap `swap` @endlink</td>
diff --git a/src/json.hpp b/src/json.hpp
index a302bb02..3c8d3f82 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -5053,6 +5053,90 @@ class basic_json
         return *this;
     }
 
+    /*!
+    @brief add an object to an array
+
+    Creates a JSON value from the passed parameters @a args to the end of the
+    JSON value. If the function is called on a JSON null value, an empty array
+    is created before appending the value created from @a args.
+
+    @param[in] args arguments to forward to a constructor of @ref basic_json
+    @tparam Args compatible types to create a @ref basic_json object
+
+    @throw std::domain_error when called on a type other than JSON array or
+    null; example: `"cannot use emplace_back() with number"`
+
+    @complexity Amortized constant.
+
+    @liveexample{The example shows how `push_back()` can be used to add
+    elements to a JSON array. Note how the `null` value was silently converted
+    to a JSON array.,emplace_back}
+
+    @since version 2.0.8
+    */
+    template<class... Args>
+    void emplace_back(Args&& ... args)
+    {
+        // emplace_back only works for null objects or arrays
+        if (not(is_null() or is_array()))
+        {
+            throw std::domain_error("cannot use emplace_back() with " + type_name());
+        }
+
+        // transform null object into an array
+        if (is_null())
+        {
+            m_type = value_t::array;
+            m_value = value_t::array;
+            assert_invariant();
+        }
+
+        // add element to array (perfect forwarding)
+        m_value.array->emplace_back(std::forward<Args>(args)...);
+    }
+
+    /*!
+    @brief add an object to an object
+
+    Creates a JSON value from the passed parameters @a args to the JSON
+    object. If the function is called on a JSON null value, an empty object
+    is created before appending the value created from @a args.
+
+    @param[in] args arguments to forward to a constructor of @ref basic_json
+    @tparam Args compatible types to create a @ref basic_json object
+
+    @throw std::domain_error when called on a type other than JSON object or
+    null; example: `"cannot use emplace() with number"`
+
+    @complexity Logarithmic in the size of the container, O(log(`size()`)).
+
+    @liveexample{The example shows how `emplace()` can be used to add elements
+    to a JSON object. Note how the `null` value was silently converted to a
+    JSON object.,emplace}
+
+    @since version 2.0.8
+    */
+    template<class... Args>
+    void emplace(Args&& ... args)
+    {
+        // emplace only works for null objects or arrays
+        if (not(is_null() or is_object()))
+        {
+            throw std::domain_error("cannot use emplace() with " + type_name());
+        }
+
+        // transform null object into an object
+        if (is_null())
+        {
+            m_type = value_t::object;
+            m_value = value_t::object;
+            assert_invariant();
+        }
+
+        // add element to array (perfect forwarding)
+        m_value.object->emplace(std::forward<Args>(args)...);
+    }
+
     /*!
     @brief inserts element
 
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index b829889d..3173d799 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -5053,6 +5053,90 @@ class basic_json
         return *this;
     }
 
+    /*!
+    @brief add an object to an array
+
+    Creates a JSON value from the passed parameters @a args to the end of the
+    JSON value. If the function is called on a JSON null value, an empty array
+    is created before appending the value created from @a args.
+
+    @param[in] args arguments to forward to a constructor of @ref basic_json
+    @tparam Args compatible types to create a @ref basic_json object
+
+    @throw std::domain_error when called on a type other than JSON array or
+    null; example: `"cannot use emplace_back() with number"`
+
+    @complexity Amortized constant.
+
+    @liveexample{The example shows how `push_back()` can be used to add
+    elements to a JSON array. Note how the `null` value was silently converted
+    to a JSON array.,emplace_back}
+
+    @since version 2.0.8
+    */
+    template<class... Args>
+    void emplace_back(Args&& ... args)
+    {
+        // emplace_back only works for null objects or arrays
+        if (not(is_null() or is_array()))
+        {
+            throw std::domain_error("cannot use emplace_back() with " + type_name());
+        }
+
+        // transform null object into an array
+        if (is_null())
+        {
+            m_type = value_t::array;
+            m_value = value_t::array;
+            assert_invariant();
+        }
+
+        // add element to array (perfect forwarding)
+        m_value.array->emplace_back(std::forward<Args>(args)...);
+    }
+
+    /*!
+    @brief add an object to an object
+
+    Creates a JSON value from the passed parameters @a args to the JSON
+    object. If the function is called on a JSON null value, an empty object
+    is created before appending the value created from @a args.
+
+    @param[in] args arguments to forward to a constructor of @ref basic_json
+    @tparam Args compatible types to create a @ref basic_json object
+
+    @throw std::domain_error when called on a type other than JSON object or
+    null; example: `"cannot use emplace() with number"`
+
+    @complexity Logarithmic in the size of the container, O(log(`size()`)).
+
+    @liveexample{The example shows how `emplace()` can be used to add elements
+    to a JSON object. Note how the `null` value was silently converted to a
+    JSON object.,emplace}
+
+    @since version 2.0.8
+    */
+    template<class... Args>
+    void emplace(Args&& ... args)
+    {
+        // emplace only works for null objects or arrays
+        if (not(is_null() or is_object()))
+        {
+            throw std::domain_error("cannot use emplace() with " + type_name());
+        }
+
+        // transform null object into an object
+        if (is_null())
+        {
+            m_type = value_t::object;
+            m_value = value_t::object;
+            assert_invariant();
+        }
+
+        // add element to array (perfect forwarding)
+        m_value.object->emplace(std::forward<Args>(args)...);
+    }
+
     /*!
     @brief inserts element
 
diff --git a/test/src/unit-modifiers.cpp b/test/src/unit-modifiers.cpp
index fd7fed56..499edde7 100644
--- a/test/src/unit-modifiers.cpp
+++ b/test/src/unit-modifiers.cpp
@@ -258,6 +258,74 @@ TEST_CASE("modifiers")
         }
     }
 
+    SECTION("emplace_back()")
+    {
+        SECTION("to array")
+        {
+            SECTION("null")
+            {
+                json j;
+                j.emplace_back(1);
+                j.emplace_back(2);
+                CHECK(j.type() == json::value_t::array);
+                CHECK(j == json({1, 2}));
+            }
+
+            SECTION("array")
+            {
+                json j = {1, 2, 3};
+                j.emplace_back("Hello");
+                CHECK(j.type() == json::value_t::array);
+                CHECK(j == json({1, 2, 3, "Hello"}));
+            }
+
+            SECTION("multiple values")
+            {
+                json j;
+                j.emplace_back(3, "foo");
+                CHECK(j.type() == json::value_t::array);
+                CHECK(j == json({{"foo", "foo", "foo"}}));
+            }
+        }
+
+        SECTION("other type")
+        {
+            json j = 1;
+            CHECK_THROWS_AS(j.emplace_back("Hello"), std::domain_error);
+            CHECK_THROWS_WITH(j.emplace_back("Hello"), "cannot use emplace_back() with number");
+        }
+    }
+
+    SECTION("emplace()")
+    {
+        SECTION("to object")
+        {
+            SECTION("null")
+            {
+                json j;
+                j.emplace("foo", "bar");
+                j.emplace("baz", "bam");
+                CHECK(j.type() == json::value_t::object);
+                CHECK(j == json({{"baz", "bam"}, {"foo", "bar"}}));
+            }
+
+            SECTION("object")
+            {
+                json j = {{"foo", "bar"}};
+                j.emplace("baz", "bam");
+                CHECK(j.type() == json::value_t::object);
+                CHECK(j == json({{"baz", "bam"}, {"foo", "bar"}}));
+            }
+        }
+
+        SECTION("other type")
+        {
+            json j = 1;
+            CHECK_THROWS_AS(j.emplace("foo", "bar"), std::domain_error);
+            CHECK_THROWS_WITH(j.emplace("foo", "bar"), "cannot use emplace() with number");
+        }
+    }
+
     SECTION("operator+=")
     {
         SECTION("to array")