我开始使用 Boost.Hana,想知道是否有办法反序列化回 Boost.Hana 已知的 Struct。例如,我知道将这样的 Struct 序列化为 json 字符串非常简单,但我没有找到任何关于其他方式的信息。目前是不可能用 Boost.Hana 反序列化数据还是我错过了什么?
问问题
2058 次
2 回答
14
Hana 是一个元编程库。它提供了可用于构建更复杂功能(如序列化)的工具,但它本身不提供此类功能。这根本不是该库的范围。此外,关于您的特定用例;解析不是一个简单的问题,Boost.Spirit 等其他库已经尝试解决它。
话虽如此,我画了一个使用 Hana 反序列化 JSON 的示例。结果既不高效也不可靠,但它应该足以让您了解如何使用 Hana 来实现更好的目标。正确解决这个问题需要实现一个解析器组合库 à-la 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);
}
完整示例可在此处获得。
于 2015-10-12T15:00:56.033 回答
1
boost::hana json 编码器并不完整(例如,它不会转义引号): http: //www.boost.org/doc/libs/1_61_0/libs/hana/doc/html/index.html#tutorial -内省-json
要反序列化,我会使用boost::spirit::x3:http ://ciere.com/cppnow15/x3_docs/index.html
他们有一个 json 反序列化器示例:https ://github.com/cierelabs/json_spirit
于 2016-08-21T00:13:55.117 回答