![]() |
JSON documents are stored in memory using instances of value
: a SemiRegular
type which satisfies DefaultConstructible
and Copyable.
These instances are implemented as a tagged
union, and can dynamically store any of the six defined
JSON value types:
std::vector
.
std::string
true
or false
.
nullptr
.
A default constructed value
and a value constructed from
nullptr
produces a null JSON
element:
value jv1; value jv2( nullptr );
The member function value::kind
may be used to query the kind
stored in the value. Alternatively, member functions like value::is_object
or value::is_number
may be used to check whether
or not the value is a particular kind:
value jv( kind::object ); assert( jv.kind() == kind::object ); assert( jv.is_object() ); assert( ! jv.is_number() );
After a value
is constructed, its kind can change depending on what is assigned to it,
or by calling functions like value::emplace_array
or value::emplace_bool
. In all cases, the
previous contents of the value are destroyed:
value jv; jv = value( kind::array ) assert( jv.is_array() ); jv.emplace_string(); assert( jv.is_string() );
Table 1. value
Accessors
Kind |
Representation |
Emplacement |
Membership |
Checked Access |
Unchecked Access |
Pointer Access |
---|---|---|---|---|---|---|
--- |
--- |
--- |
The emplace members of value
return a suitably typed reference to the underlying container representing
the kind. For example, the call to value::emplace_string
above returns a
string&
. The library provides a suitable
type for each possible value of kind
(except for nulls). This table
shows the types corresponding to each kind:
Kind |
Type |
Description |
---|---|---|
An associative array of string keys mapping to |
||
An ordered list of |
||
A UTF-8
encoded Unicode
string
of characters with an interface similar to |
||
|
A type representing an integral or floating point number. |
|
A |
||
A monostate value representing null. |
We can use the emplace return value to perform an assignment or to capture a reference to the underlying representation for later inspection or modification:
value jv; jv.emplace_string() = "Hello, world!"; number& num = jv.emplace_number(); // changes to kind::number num = 1;
If the kind
of a value is already known, functions such as value::as_bool
or value::as_string
may be used to obtain
a reference to the underlying representation without changing the existing
value:
value jv( kind::bool ); jv.as_bool() = true; jv.as_string() = "Hello, world!"; // throws system_error !!
However, as shown above these functions throw an exception if the kind in the value does not match the kind implied by the function signature. This can be used as a concise form of validation: access values as if they were the right type, but handle the resulting exception indicating if the schema of the JSON is not valid.
We can query a value for its underlying representation of a particular kind
in a way that does not throw exceptions by requesting a pointer which may
be null, instead of a reference. Here we use value::if_string
to conditionally perform
an assignment without using exceptions:
value jv( kind::string ); if(auto ptr = jv.if_string()) *ptr = "Hello, world!";
![]() |
Tip |
---|---|
If the value's kind is known statically, a reference to the underlying
representation may be obtained by dereferencing the pointer without checking.
This avoids the code overhead of the possible exception when using, for
example value jv( kind::string ); *jv.if_string() = "Hello, world!"; // The compiler's static analysis can see that // a null pointer is never dereferenced above. |