Value Conversion
While the value
container makes it easy to create ad-hoc structures,
often it is necessary to convert between JSON and user-defined types or types
from the standard library.
The function template value_from
provides an interface to construct
a value
from a type T
. The function template value_to
converts in the opposite direction, from a type T
to value
. Both
support a wide variety of different
fundamental types, such as
int
or double
, standard library types, such as std::string
or
std::vector<T>
, and can be extended to support user-defined types.
std::vector< int > v1{ 1, 2, 3, 4 };
// Convert the vector to a JSON array
value jv = value_from( v1 );
assert( serialize( jv ) == R"([1,2,3,4])" );
// Convert back to vector< int >
std::vector< int > v2 = value_to< std::vector< int > >( jv );
assert( v1 == v2 );
For the type T
, the appropriate conversion approach is chosen from the
following list of categories. The first matching category is selected.
Category of T | Comment | value_from behavior |
value_to behavior |
---|---|---|---|
Custom conversion. |
Custom behavior. |
Custom behavior. |
|
Boost.JSON container. |
The result is equal to the input value. |
The result is equal to the input value. |
|
|
The result is equal to the input value. |
The result is equal to the input value. |
|
The result is a number equal to input and has the type
|
The result is created via |
||
Type satisfying |
Intended for types like |
The result is a null value. |
The result is default-constructed. |
Type satisfying |
A sequence of |
The result is a |
The result is constructed from a |
Type satisfying |
A one-to-one mapping (e.g. |
The result is an |
The result is default-constructed, and elements are |
Type satisfying |
A sequence of elements, e.g. |
The result is an |
The result is default-constructed, and elements are |
Type satisfying |
A heterogenous sequence with fixed size, e.g. |
The result is an |
The result is constructed with the array elements as constructor arguments. |
Type satisfying |
The result is an |
The result is default-constructed and described members are assigned corresponding values. |
|
Type satisfying |
If the input value is equal to one of the described enumerators, the result is
a |
The result is the described enumerator, corresponding to the input
|
|
Type satisfying |
|
The result is equal to the result of conversion of the active variant alternative. |
The result holds the first alternative for which a conversion succeeds. |
Type satisfying |
If the input value is empty, the result is a |
The result is default constructed if the input value is |
|
Type satisfying |
|
The result is equal to the result of |
The result is constructed from two pointers to |
For composite types (sequences, tuples, described classes, etc.) conversion of contained objects is applied recursively. For example:
std::map< std::string, std::pair<int, bool> > m = {
{"a", {1, false}},
{"b", {4, true}},
{"c", {5, false}},
};
value jv = value_from( m );
assert(( jv == object{
{"a", array{1, false}},
{"b", array{4, true}},
{"c", array{5, false}},
}));
Here, the map is converted into an object
, since it matches
is_map_like
. Each of its keys is converted into a string
, as
std::string
matches is_string_like
, and each of its values is
converted into an array
, as std::pair
matches is_tuple_like
.
Finally, elements of pairs are converted into a std::int64_t
number and
a bool
.