...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
In order to allow conveniently retrieving and changing deeply nested elements
of value
objects the library implements RFC
6901 (JSON Pointer):
value jv = { {"one", 1}, {"two", 2} }; assert( jv.at("one") == jv.at_pointer("/one") ); jv.at_pointer("/one") = {{"foo", "bar"}}; assert( jv.at("one").at("foo") == jv.at_pointer("/one/foo") ); jv.at_pointer("/one/foo") = {true, 4, "qwerty"}; assert( jv.at("one").at("foo").at(1) == jv.at_pointer("/one/foo/1") );
This is particularly useful when throwing exceptions is undesirable. For example, compare
object* obj = jv.if_object(); if( !obj ) return nullptr; value* val = obj->if_contains("one"); if( !val ) return nullptr; obj = val->if_object(); if( !obj ) return nullptr; val = obj->if_contains("foo"); if( !val ) return nullptr; array* arr = val->if_array(); if( !arr ) return nullptr; return arr->if_contains(1);
with
boost::system::error_code ec; return jv.find_pointer("/one/foo/1", ec);
The library also allows changing and adding deeply nested elements. The function
set_at_pointer
traverses the value
similarly to at_pointer
, but additionally, it
can create missing elements in certain cases:
value jv; jv.set_at_pointer("/two/bar/0", 12); assert( jv.is_object() ); assert( jv.at_pointer("/two").is_object() ); assert( jv.at_pointer("/two/bar").is_array() ); assert( jv.at_pointer("/two/bar/0") == 12 );
The specific behavior is controlled by an optional parameter of type set_pointer_options
.
For example, here's the same example with a different option:
set_pointer_options opts; opts.create_arrays = false; jv.set_at_pointer("/two/bar/0", 12, opts); assert( jv.is_object() ); assert( jv.at_pointer("/two").is_object() ); assert( jv.at_pointer("/two/bar").is_object() ); // object, not array assert( jv.at_pointer("/two/bar/0") == 12 );