用于增强序列化的与顺序无关的输入存档
Order-independent input archive for boost serialization
我用boost::serialization,非常喜欢。我有时会想念的唯一一件事是当我想从 xml 存档中读取配置输入结构时。那就太好了,if
- xml 结构可以与顺序无关并且
- 如果 xml 中缺少对象,将采用 class 的默认值。
这主要适用于 boost::serialization 还是您已经有解决方案?
序列化不是为了这个。
当然你可以让你序列化的东西无论如何都与顺序无关:
#include <boost/serialization/map.hpp>
struct MyConfig {
std::map<std::string, std::string> values;
template<typename Ar> void serialize(Ar& ar, unsigned) {
ar & values;
}
};
阅读顺序无关紧要。
此外,您已经可以使用可选的默认值(提示:它与序列化完全无关):
struct MyConfig {
std::string const& workingDirectory() {
return *values.emplace("workingdir", "$HOME").first;
}
private:
std::unordered_map<std::string, std::string> values;
};
此处 workingDirectory()
将 return 对反序列化值的引用。如果不存在这样的值,将首先插入 "$HOME"
。
然而
您应该考虑在这种情况下使用 Boost Property Tree。它更适合这个目的。
因为我认为展示而不是讲述更有建设性,下面是我认为您在使用 Boost 后的示例 属性 树:
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
struct Config {
std::string order;
double independent;
std::string stuff;
static Config load_xml(std::istream& from) {
boost::property_tree::ptree pt;
read_xml(from, pt);
return {
pt.get("order", "default property value for order"),
pt.get("independent", 42.0),
pt.get("stuff", "no stuff configured")
};
}
void save_xml(std::ostream& to) const {
boost::property_tree::ptree pt;
if (!order.empty()) pt.put("order", order);
if (independent != 0) pt.put("independent", independent);
if (!stuff.empty()) pt.put("stuff", stuff);
write_xml(to, pt);
}
};
#include <iostream>
int main() {
{
Config cfg { "order", 999, "stuff" };
cfg.save_xml(std::cout);
}
std::istringstream iss("<independent>3.1415926535897931</independent><IGNORED>stuff</IGNORED><order>LOOK MA</order>");
Config::load_xml(iss).save_xml(std::cout);
}
打印:
<?xml version="1.0" encoding="utf-8"?>
<order>order</order><independent>999</independent><stuff>stuff</stuff>
<?xml version="1.0" encoding="utf-8"?>
<order>LOOK MA</order><independent>3.1415926535897931</independent><stuff>no stuff configured</stuff>
here 是我的实验性 boost::serialization 存档,它能够序列化为 boost::property_tree.
默认情况下,生成的 ptree 是以适合 json 或信息格式的方式创建的,但只需稍作修改即可针对 xml.
进行优化
它可以按任意顺序加载字段,也可以忽略其他字段(这允许一些向前兼容)。
当前错过的字段将产生错误。引入具有默认值的可选字段需要一些额外的工作。
还有一个 patch for xml archive 允许跳过未知字段,但它不允许任意顺序或可选字段。
我用boost::serialization,非常喜欢。我有时会想念的唯一一件事是当我想从 xml 存档中读取配置输入结构时。那就太好了,if
- xml 结构可以与顺序无关并且
- 如果 xml 中缺少对象,将采用 class 的默认值。
这主要适用于 boost::serialization 还是您已经有解决方案?
序列化不是为了这个。
当然你可以让你序列化的东西无论如何都与顺序无关:
#include <boost/serialization/map.hpp>
struct MyConfig {
std::map<std::string, std::string> values;
template<typename Ar> void serialize(Ar& ar, unsigned) {
ar & values;
}
};
阅读顺序无关紧要。
此外,您已经可以使用可选的默认值(提示:它与序列化完全无关):
struct MyConfig {
std::string const& workingDirectory() {
return *values.emplace("workingdir", "$HOME").first;
}
private:
std::unordered_map<std::string, std::string> values;
};
此处 workingDirectory()
将 return 对反序列化值的引用。如果不存在这样的值,将首先插入 "$HOME"
。
然而
您应该考虑在这种情况下使用 Boost Property Tree。它更适合这个目的。
因为我认为展示而不是讲述更有建设性,下面是我认为您在使用 Boost 后的示例 属性 树:
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
struct Config {
std::string order;
double independent;
std::string stuff;
static Config load_xml(std::istream& from) {
boost::property_tree::ptree pt;
read_xml(from, pt);
return {
pt.get("order", "default property value for order"),
pt.get("independent", 42.0),
pt.get("stuff", "no stuff configured")
};
}
void save_xml(std::ostream& to) const {
boost::property_tree::ptree pt;
if (!order.empty()) pt.put("order", order);
if (independent != 0) pt.put("independent", independent);
if (!stuff.empty()) pt.put("stuff", stuff);
write_xml(to, pt);
}
};
#include <iostream>
int main() {
{
Config cfg { "order", 999, "stuff" };
cfg.save_xml(std::cout);
}
std::istringstream iss("<independent>3.1415926535897931</independent><IGNORED>stuff</IGNORED><order>LOOK MA</order>");
Config::load_xml(iss).save_xml(std::cout);
}
打印:
<?xml version="1.0" encoding="utf-8"?>
<order>order</order><independent>999</independent><stuff>stuff</stuff>
<?xml version="1.0" encoding="utf-8"?>
<order>LOOK MA</order><independent>3.1415926535897931</independent><stuff>no stuff configured</stuff>
here 是我的实验性 boost::serialization 存档,它能够序列化为 boost::property_tree.
默认情况下,生成的 ptree 是以适合 json 或信息格式的方式创建的,但只需稍作修改即可针对 xml.
进行优化它可以按任意顺序加载字段,也可以忽略其他字段(这允许一些向前兼容)。
当前错过的字段将产生错误。引入具有默认值的可选字段需要一些额外的工作。
还有一个 patch for xml archive 允许跳过未知字段,但它不允许任意顺序或可选字段。