Add json_object_update_recursive()
Support merging values nested within objects. For instance, merging: { "foo": 1, "bar": { "baz": 2 } } with { "bar": { "baz": 3 } } results in { "foo": 1, "bar": { "baz": 3 } } instead of overwriting the value for the bar key.
This commit is contained in:
parent
672b6df474
commit
cb4727c4a9
@ -708,6 +708,12 @@ allowed in object keys.
|
||||
|
||||
.. versionadded:: 2.3
|
||||
|
||||
.. function:: int json_object_update_recursive(json_t *object, json_t *other)
|
||||
|
||||
Like :func:`json_object_update()`, but object values in *other* are
|
||||
recursively merged with the corresponding values in *object* if they are also
|
||||
objects, instead of overwriting them. Returns 0 on success or -1 on error.
|
||||
|
||||
.. function:: json_object_foreach(object, key, value)
|
||||
|
||||
Iterate over every key-value pair of ``object``, running the block
|
||||
|
@ -41,6 +41,7 @@ EXPORTS
|
||||
json_object_update
|
||||
json_object_update_existing
|
||||
json_object_update_missing
|
||||
json_object_update_recursive
|
||||
json_object_iter
|
||||
json_object_iter_at
|
||||
json_object_iter_next
|
||||
|
@ -199,6 +199,7 @@ int json_object_clear(json_t *object);
|
||||
int json_object_update(json_t *object, json_t *other);
|
||||
int json_object_update_existing(json_t *object, json_t *other);
|
||||
int json_object_update_missing(json_t *object, json_t *other);
|
||||
int json_object_update_recursive(json_t *object, json_t *other);
|
||||
void *json_object_iter(json_t *object);
|
||||
void *json_object_iter_at(json_t *object, const char *key);
|
||||
void *json_object_key_to_iter(const char *key);
|
||||
|
20
src/value.c
20
src/value.c
@ -214,6 +214,26 @@ int json_object_update_missing(json_t *object, json_t *other)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int json_object_update_recursive(json_t *object, json_t *other)
|
||||
{
|
||||
const char *key;
|
||||
json_t *value;
|
||||
|
||||
if(!json_is_object(object) || !json_is_object(other))
|
||||
return -1;
|
||||
|
||||
json_object_foreach(other, key, value) {
|
||||
json_t *v = json_object_get(object, key);
|
||||
|
||||
if(json_is_object(v) && json_is_object(value))
|
||||
json_object_update_recursive(v, value);
|
||||
else
|
||||
json_object_set_nocheck(object, key, value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *json_object_iter(json_t *json)
|
||||
{
|
||||
json_object_t *object;
|
||||
|
@ -207,6 +207,57 @@ static void test_conditional_updates()
|
||||
json_decref(other);
|
||||
}
|
||||
|
||||
static void test_recursive_updates()
|
||||
{
|
||||
json_t *invalid, *object, *other;
|
||||
|
||||
invalid = json_integer(42);
|
||||
|
||||
object = json_pack("{sis{si}}", "foo", 1, "bar", "baz", 2);
|
||||
other = json_pack("{sisisi}", "foo", 3, "bar", 4, "baz", 5);
|
||||
|
||||
if(!json_object_update_recursive(invalid, other))
|
||||
fail("json_object_update_recursive accepted non-object argument");
|
||||
|
||||
json_decref(invalid);
|
||||
|
||||
if(json_object_update_recursive(object, other))
|
||||
fail("json_object_update_recursive failed");
|
||||
|
||||
if(json_object_size(object) != 3)
|
||||
fail("invalid size after update");
|
||||
|
||||
if(json_integer_value(json_object_get(object, "foo")) != 3)
|
||||
fail("json_object_update_recursive failed to update existing key");
|
||||
|
||||
if(json_integer_value(json_object_get(object, "bar")) != 4)
|
||||
fail("json_object_update_recursive failed to overwrite object");
|
||||
|
||||
if(json_integer_value(json_object_get(object, "baz")) != 5)
|
||||
fail("json_object_update_recursive didn't add new item");
|
||||
|
||||
json_decref(object);
|
||||
json_decref(other);
|
||||
|
||||
object = json_pack("{sis{si}}", "foo", 1, "bar", "baz", 2);
|
||||
other = json_pack("{s{si}}", "bar", "baz", 3);
|
||||
|
||||
if(json_object_update_recursive(object, other))
|
||||
fail("json_object_update_recursive failed");
|
||||
|
||||
if(json_object_size(object) != 2)
|
||||
fail("invalid size after update");
|
||||
|
||||
if(!json_object_get(object, "foo"))
|
||||
fail("json_object_update_recursive removed existing key");
|
||||
|
||||
if(json_integer_value(json_object_get(json_object_get(object, "bar"), "baz")) != 3)
|
||||
fail("json_object_update_recursive failed to update nested value");
|
||||
|
||||
json_decref(object);
|
||||
json_decref(other);
|
||||
}
|
||||
|
||||
static void test_circular()
|
||||
{
|
||||
json_t *object1, *object2;
|
||||
@ -667,6 +718,7 @@ static void run_tests()
|
||||
test_update();
|
||||
test_set_many_keys();
|
||||
test_conditional_updates();
|
||||
test_recursive_updates();
|
||||
test_circular();
|
||||
test_set_nocheck();
|
||||
test_iterators();
|
||||
|
Loading…
Reference in New Issue
Block a user