Is it possible to deserialize using Boost.Hana?

I get started with Boost.Hana and wonder if there is a way to deserialize back to Struct, which is known by Boost.Hana. I know that it is quite simple to serialize such a Struct into a json string, for example, but I have not found any information about this. Currently, it is just not possible to deserialize data using Boost.Hana or am I missing something?

+5
source share
2 answers

Hana is a metaprogramming library. It provides tools that you can use to build more complex functions, such as serialization, but do not provide such functionality. This is simply not the volume of this library. In addition, regarding your specific use case; parsing is not an easy problem, and other libraries like Boost.Spirit are already trying to solve it.

Having said that, I sketched an example of using Hana to deserialize JSON. The result is neither effective nor reliable, but it should be enough to give you see how Khan can be used to achieve something better. Solving this problem would correctly require the implementation of the à-la Boost.Spirit parser combinatorial library, which I will not do here. Here you are:

template <typename T> std::enable_if_t<std::is_same<T, int>::value, T> from_json(std::istream& in) { T result; in >> result; return result; } template <typename T> std::enable_if_t<std::is_same<T, std::string>::value, T> from_json(std::istream& in) { char quote; in >> quote; T result; char c; while (in.get(c) && c != '"') { result += c; } return result; } template <typename T> std::enable_if_t<hana::Struct<T>::value, T> from_json(std::istream& in) { T result; char brace; in >> brace; hana::for_each(hana::keys(result), [&](auto key) { in.ignore(std::numeric_limits<std::streamsize>::max(), ':'); auto& member = hana::at_key(result, key); using Member = std::remove_reference_t<decltype(member)>; member = from_json<Member>(in); }); in >> brace; return result; } template <typename Xs> std::enable_if_t<hana::Sequence<Xs>::value, Xs> from_json(std::istream& in) { Xs result; char bracket; in >> bracket; hana::length(result).times.with_index([&](auto i) { if (i != 0u) { char comma; in >> comma; } auto& element = hana::at(result, i); using Element = std::remove_reference_t<decltype(element)>; element = from_json<Element>(in); }); in >> bracket; return result; } 

And then you can use it as

 struct Car { BOOST_HANA_DEFINE_STRUCT(Car, (std::string, brand), (std::string, model) ); }; struct Person { BOOST_HANA_DEFINE_STRUCT(Person, (std::string, name), (std::string, last_name), (int, age) ); }; int main() { std::istringstream json(R"EOS( [ { "name": "John", "last_name": "Doe", "age": 30 }, { "brand": "BMW", "model": "Z3" }, { "brand": "Audi", "model": "A4" } ] )EOS"); auto actual = from_json<hana::tuple<Person, Car, Car>>(json); auto expected = hana::make_tuple(Person{"John", "Doe", 30}, Car{"BMW", "Z3"}, Car{"Audi", "A4"}); assert(actual == expected); } 

A complete example is available here .

+10
source

The boost :: hana json encoder is not a compiler (for example, it does not escape quotes): http://www.boost.org/doc/libs/1_61_0/libs/hana/doc/html/index.html#tutorial-introspection- json

To de-serialize, I would use boost :: spirit :: x3 : http://ciere.com/cppnow15/x3_docs/index.html

They have an example json deserializer: https://github.com/cierelabs/json_spirit

0
source

Source: https://habr.com/ru/post/1233466/


All Articles