Можно ли десериализовать с помощью Boost.Hana?

Я начинаю с Boost.Hana и мне было интересно, есть ли способ десериализации обратно в Struct, который известен Boost.Hana.
Я знаю, что довольно просто сериализовать такой Struct, например, в строку json, но я не нашел никакой информации об обратном.
В настоящее время просто невозможно десериализовать данные с помощью Boost.Hana или я что-то упустил?

6

Решение

Хана — это библиотека метапрограммирования. Он предоставляет инструменты, которые могут быть использованы для создания
более сложный функционал, такой как сериализация, но он не обеспечивает такой
сам функционал. Это просто не сфера этой библиотеки. Также относительно
ваш конкретный вариант использования; разбор не простая проблема и других библиотек
вроде Boost.Spirit уже попробуй это решить.

При этом я набросал пример использования Hana для десериализации JSON.
Результат не является ни эффективным, ни надежным, но этого должно быть достаточно, чтобы дать
Вы мельком видите, как Хана может быть использована для достижения чего-то лучшего. Решение
эта проблема правильно потребует реализации библиотеки комбинатора анализатора
а-ля Boost.Spirit, чего я здесь не буду делать. Ну вот:

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;
}

И тогда вы можете использовать его как

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);
}

Полный пример доступен Вот.

11

Другие решения

Кодер boost :: hana json не является конкурентом (например, он не экранирует кавычки): http://www.boost.org/doc/libs/1_61_0/libs/hana/doc/html/index.html#tutorial-introspection-json

Для десериализации я бы использовал повышение :: дух :: x3: http://ciere.com/cppnow15/x3_docs/index.html

У них есть пример десериализатора JSON: https://github.com/cierelabs/json_spirit

0

По вопросам рекламы [email protected]