2

Json-C has this clumsy and poorly-documented reference counting which is giving us problems. In particular, we have an object containing children, and want to replace a particular child with

json_object_object_add(parent, "child name", new_child).

Now we know that this transfers ownership of new_child, that's no problem. But what about the old child? We could manually remove it with json_object_object_del, which doesn't delete the old child (but leaks it). So it appears the following solution is a proper replacement:

json_object *manual = json_object_object_get(parent, "child name");
json_object_object_del(parent, "child name");
json_object_put(manual);
json_object_object_add(parent, "child name", new_child);

However, we're wondering if json_object_object_add is smart enough to make the first three steps redundant. This would be a better design because we'd prefer an atomic replacement - if the new child cannot be added for whatever reason, we should keep the old child.

MSalters
  • 173,980
  • 10
  • 155
  • 350

1 Answers1

2

In version 0.12 you don't have to. The function looks like this:

void json_object_object_add(struct json_object* jso, const char *key,
                struct json_object *val)
{
    // We lookup the entry and replace the value, rather than just deleting
    // and re-adding it, so the existing key remains valid.
    json_object *existing_value = NULL;
    struct lh_entry *existing_entry;
    existing_entry = lh_table_lookup_entry(jso->o.c_object, (void*)key);
    if (!existing_entry)
    {
        lh_table_insert(jso->o.c_object, strdup(key), val);
        return;
    }
    existing_value = (void *)existing_entry->v;
    if (existing_value)
        json_object_put(existing_value);
    existing_entry->v = val;
}
BlackJack
  • 4,476
  • 1
  • 20
  • 25