Dotted-string paths
Paths are keys separated by ., with array elements addressed by [N] suffixes:
"database.host" "retries[2]" "servers[0].port" "matrix[1][2]"
Only ., [ and ] are special, so a key with spaces works ("database.connection timeout"); a key that itself contains . or [ cannot be addressed by a path (an accepted limitation).
A malformed path resolves to nothing — never to an exception.
Typed getters
std::string s = doc.getString ( "database.host", "localhost" );
long long i = doc.getInteger( "database.port", 5432 );
double d = doc.getDouble ( "ratio", 1.0 );
bool b = doc.getBoolean( "verbose", false );
The second argument is the fallback, used when the path is missing or the value has the wrong type. getInteger truncates any number.
Presence vs. value
doc.containsPath( "database.pool" ); // bool
Value* v = doc.findPath( "database.pool" ); // nullptr if missing
Value& r = doc.atPath( "database.pool" ); // throws std::out_of_range
Walking the model
Object& root = doc.getRoot(); // throws if the root is not an object
if( Value* v = root.findPath( "database.port" ) )
if( Number* n = v->asNumber() )
std::cout << n->asInteger() << '\n';
as*() casts return nullptr on a type mismatch — no dynamic_cast, no exception. Value::Type plus isObject() / isArray() / isString() / … let you branch first.
The query API addresses members by name (find / at / contains), not by index. To iterate, drop to the member API and skip the disabled ones yourself:
for( std::size_t k = 0; k < root.memberCount(); ++k )
{
Member const& m = root.getMember( k );
if( m.isDisabled() ) continue;
// m.getKey(), m.getValue()
}
Disabled members are invisible
Every query entry point above — paths, getX, contains, find, at, size — skips disabled members. To see them, use the member API (memberCount / getMember) — see Object — member API.
Multi-line values
A |-block string reads back as one value with newlines:
banner: |Welcome
|to the app
doc.getString( "banner" ); // "Welcome\nto the app\n"

