Commit 84138864 authored by Kevin Hurley's avatar Kevin Hurley Committed by facebook-github-bot-9

Add ability to merge dynamic objects

Summary: Adding ability to merge dynamic objects with another object.  It will just overwrite duplicate keys

Reviewed By: @yfeldblum

Differential Revision: D2413628
parent 09e6623e
......@@ -512,6 +512,41 @@ template<class K, class V> inline void dynamic::insert(K&& key, V&& val) {
rv.first->second = std::forward<V>(val);
}
inline void dynamic::update(const dynamic& mergeObj) {
if (!isObject() || !mergeObj.isObject()) {
throw TypeError("object", type(), mergeObj.type());
}
for (const auto& pair : mergeObj.items()) {
(*this)[pair.first] = pair.second;
}
}
inline void dynamic::update_missing(const dynamic& mergeObj1) {
if (!isObject() || !mergeObj1.isObject()) {
throw TypeError("object", type(), mergeObj1.type());
}
// Only add if not already there
for (const auto& pair : mergeObj1.items()) {
if ((*this).find(pair.first) == (*this).items().end()) {
(*this)[pair.first] = pair.second;
}
}
}
inline dynamic dynamic::merge(
const dynamic& mergeObj1,
const dynamic& mergeObj2) {
// No checks on type needed here because they are done in update_missing
// Note that we do update_missing here instead of update() because
// it will prevent the extra writes that would occur with update()
auto ret = mergeObj2;
ret.update_missing(mergeObj1);
return ret;
}
inline std::size_t dynamic::erase(dynamic const& key) {
auto& obj = get<ObjectImpl>();
return obj.erase(key);
......
......@@ -436,6 +436,23 @@ public:
*/
template<class K, class V> void insert(K&&, V&& val);
/*
* These functions merge two folly dynamic objects.
* The "update" and "update_missing" functions extend the object by
* inserting the key/value pairs of mergeObj into the current object.
* For update, if key is duplicated between the two objects, it
* will overwrite with the value of the object being inserted (mergeObj).
* For "update_missing", it will prefer the value in the original object
*
* The "merge" function creates a new object consisting of the key/value
* pairs of both mergeObj1 and mergeObj2
* If the key is duplicated between the two objects,
* it will prefer value in the second object (mergeObj2)
*/
void update(const dynamic& mergeObj);
void update_missing(const dynamic& other);
static dynamic merge(const dynamic& mergeObj1, const dynamic& mergeObj2);
/*
* Erase an element from a dynamic object, by key.
*
......
......@@ -98,6 +98,27 @@ TEST(Dynamic, ObjectBasics) {
// We don't allow objects as keys in objects.
EXPECT_ANY_THROW(newObject[d3] = 12);
// Merge two objects
dynamic origMergeObj1 = folly::dynamic::object();
dynamic mergeObj1 = origMergeObj1 = folly::dynamic::object
("key1", "value1")
("key2", "value2");
dynamic mergeObj2 = folly::dynamic::object
("key2", "value3")
("key3", "value4");
dynamic combinedObj = folly::dynamic::object
("key1", "value1")
("key2", "value3")
("key3", "value4");
auto newMergeObj = dynamic::merge(mergeObj1, mergeObj2);
EXPECT_EQ(newMergeObj, combinedObj);
EXPECT_EQ(mergeObj1, origMergeObj1); // mergeObj1 should be unchanged
mergeObj1.update(mergeObj2);
EXPECT_EQ(mergeObj1, combinedObj);
dynamic arr = { 1, 2, 3, 4, 5, 6 };
EXPECT_THROW(mergeObj1.update(arr), std::exception);
}
TEST(Dynamic, ObjectErase) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment