diff --git a/doc/examples/emplace.cpp b/doc/examples/emplace.cpp
index 6014a361..c3b3c3e3 100644
--- a/doc/examples/emplace.cpp
+++ b/doc/examples/emplace.cpp
@@ -13,11 +13,18 @@ int main()
std::cout << null << '\n';
// add values
- object.emplace("three", 3);
+ auto res1 = object.emplace("three", 3);
null.emplace("A", "a");
null.emplace("B", "b");
+ // the following call will not add an object, because there is already
+ // a value stored at key "B"
+ auto res2 = null.emplace("B", "c");
+
// print values
std::cout << object << '\n';
+ std::cout << *res1.first << " " << std::boolalpha << res1.second << '\n';
+
std::cout << null << '\n';
+ std::cout << *res2.first << " " << std::boolalpha << res2.second << '\n';
}
diff --git a/doc/examples/emplace.link b/doc/examples/emplace.link
index e78fd0e5..a9366c32 100644
--- a/doc/examples/emplace.link
+++ b/doc/examples/emplace.link
@@ -1 +1 @@
-online
\ No newline at end of file
+online
\ No newline at end of file
diff --git a/doc/examples/emplace.output b/doc/examples/emplace.output
index 2bc9c002..83d6f773 100644
--- a/doc/examples/emplace.output
+++ b/doc/examples/emplace.output
@@ -1,4 +1,6 @@
{"one":1,"two":2}
null
{"one":1,"three":3,"two":2}
+3 true
{"A":"a","B":"b"}
+"b" false
diff --git a/src/json.hpp b/src/json.hpp
index fdc57dff..36afd56b 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -5075,15 +5075,20 @@ class basic_json
}
/*!
- @brief add an object to an object
+ @brief add an object to an object if key does not exist
- 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.
+ Inserts a new element into a JSON object constructed in-place with the given
+ @a args if there is no element with the key in the container. 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
+ @return a pair consisting of an iterator to the inserted element, or the
+ already-existing element if no insertion happened, and a bool
+ denoting whether the insertion took place.
+
@throw std::domain_error when called on a type other than JSON object or
null; example: `"cannot use emplace() with number"`
@@ -5091,12 +5096,13 @@ class basic_json
@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}
+ JSON object. Further note how no value is added if there was already one
+ value stored with the same key.,emplace}
@since version 2.0.8
*/
template
- void emplace(Args&& ... args)
+ std::pair emplace(Args&& ... args)
{
// emplace only works for null objects or arrays
if (not(is_null() or is_object()))
@@ -5113,7 +5119,13 @@ class basic_json
}
// add element to array (perfect forwarding)
- m_value.object->emplace(std::forward(args)...);
+ auto res = m_value.object->emplace(std::forward(args)...);
+ // create result iterator and set iterator to the result of emplace
+ auto it = begin();
+ it.m_it.object_iterator = res.first;
+
+ // return pair of iterator and boolean
+ return {it, res.second};
}
/*!
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index 383f4b8f..b629dc61 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -5075,15 +5075,20 @@ class basic_json
}
/*!
- @brief add an object to an object
+ @brief add an object to an object if key does not exist
- 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.
+ Inserts a new element into a JSON object constructed in-place with the given
+ @a args if there is no element with the key in the container. 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
+ @return a pair consisting of an iterator to the inserted element, or the
+ already-existing element if no insertion happened, and a bool
+ denoting whether the insertion took place.
+
@throw std::domain_error when called on a type other than JSON object or
null; example: `"cannot use emplace() with number"`
@@ -5091,12 +5096,13 @@ class basic_json
@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}
+ JSON object. Further note how no value is added if there was already one
+ value stored with the same key.,emplace}
@since version 2.0.8
*/
template
- void emplace(Args&& ... args)
+ std::pair emplace(Args&& ... args)
{
// emplace only works for null objects or arrays
if (not(is_null() or is_object()))
@@ -5113,7 +5119,13 @@ class basic_json
}
// add element to array (perfect forwarding)
- m_value.object->emplace(std::forward(args)...);
+ auto res = m_value.object->emplace(std::forward(args)...);
+ // create result iterator and set iterator to the result of emplace
+ auto it = begin();
+ it.m_it.object_iterator = res.first;
+
+ // return pair of iterator and boolean
+ return {it, res.second};
}
/*!
diff --git a/test/src/unit-modifiers.cpp b/test/src/unit-modifiers.cpp
index 499edde7..e715d55f 100644
--- a/test/src/unit-modifiers.cpp
+++ b/test/src/unit-modifiers.cpp
@@ -302,18 +302,47 @@ TEST_CASE("modifiers")
{
SECTION("null")
{
+ // start with a null value
json j;
- j.emplace("foo", "bar");
- j.emplace("baz", "bam");
+
+ // add a new key
+ auto res1 = j.emplace("foo", "bar");
+ CHECK(res1.second == true);
+ CHECK(*res1.first == "bar");
+
+ // the null value is changed to an object
CHECK(j.type() == json::value_t::object);
+
+ // add a new key
+ auto res2 = j.emplace("baz", "bam");
+ CHECK(res2.second == true);
+ CHECK(*res2.first == "bam");
+
+ // we try to insert at given key - no change
+ auto res3 = j.emplace("baz", "bad");
+ CHECK(res3.second == false);
+ CHECK(*res3.first == "bam");
+
+ // the final object
CHECK(j == json({{"baz", "bam"}, {"foo", "bar"}}));
}
SECTION("object")
{
+ // start with an object
json j = {{"foo", "bar"}};
- j.emplace("baz", "bam");
- CHECK(j.type() == json::value_t::object);
+
+ // add a new key
+ auto res1 = j.emplace("baz", "bam");
+ CHECK(res1.second == true);
+ CHECK(*res1.first == "bam");
+
+ // add an existing key
+ auto res2 = j.emplace("foo", "bad");
+ CHECK(res2.second == false);
+ CHECK(*res2.first == "bar");
+
+ // check final object
CHECK(j == json({{"baz", "bam"}, {"foo", "bar"}}));
}
}