Boost.Serialization exposes an interface to read and write S-exprs. When you define codecs to your data structures in this manner, you’re only defining the mapping between your data structures and S-exprs. The JSON format can represent S-exprs easily through arrays.
struct Foobar {
int foo;
int bar;
int baz;
};
json::oarchive ar;
Foobar value{5, 10, 0};
ar << value;
Given the proper codecs are available, code such as the above would generate a JSON document such as:
[5, 10, 0]
However JSON users expect a different kind of serialization for their types. A common expectation would be:
{
"foo": 5,
"bar": 10,
"baz": 0
}
Nonetheless it’s still doable to use Boost.Serialization machinery and Trial.Protocol to generate this type of result. Boost.Serialization’s contract to define the S-expr mapping is an user-written function in the likes of:
template<class Archive>
void save(Archive& ar, const Foobar& value,
const unsigned int version)
{
ar << value.foo;
ar << value.bar;
ar << value.baz;
}
So we can simply add a new overload that works on JSON archives directly to define the JSON mapping:
template<class CharT>
void save(json::basic_oarchive<CharT>& ar,
const Foobar& value,
const unsigned int version)
{
ar.template save<json::token::begin_object>();
ar.save("foo");
ar.save(value.foo);
ar.save("bar");
ar.save(value.bar);
ar.save("baz");
ar.save(value.baz);
ar.template save<json::token::end_object>();
}
Internally Trial.Protocol does more stuff to reuse S-exprs mappings mixed with
JSON mappings, but that’s basically what you need to understand. If you use
boost::hana::Struct
to describe your types then Trial.Protocol already offers
the JSON mapping for free:
struct Foobar {
BOOST_HANA_DEFINE_STRUCT(Foobar,
(int, foo),
(int, bar),
(int, baz)
);
};
json::oarchive ar;
Foobar value{5, 10, 0};
ar << value;
And this code will generate the expected JSON:
{
"foo": 5,
"bar": 10,
"baz": 0
}