我如何决定 Boost 属性 Tree 使用的数据类型?
How can i decide the datatype Boost Property Tree uses?
我在项目中使用 Boost 属性 树时遇到了一个问题。我是这样使用它的:
using Namespace boost::property_tree;
ptree proot;
int myInt = 5;
proot.put("Number", myInt);
write_json("myjson.json", proot);
如果我这样使用它,安全的数据类型是字符串,而不是整数。我的意思的一个例子:
{ "Number": "5" } //what i get
{ "Number": 5 } //what i want
有办法改变吗?
不,你不能改变这种行为,因为字符串值类型已经融入 boost::property_tree
。虽然从技术上讲,您可以使用与默认参数不同的模板类型参数,但您丢失了进入该库的大部分转换逻辑。
作为一个有点古怪的替代方案,请考虑以下内容。
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
using namespace boost::property_tree;
using boost::property_tree::json_parser::create_escapes;
void writeJsonValue(std::ostream& stream, const ptree& pt)
{
const auto raw = pt.get_value<std::string>();
if (raw == "true" || raw == "false") {
stream << raw;
return;
}
if (const auto integral = pt.get_value_optional<int>())
stream << *integral;
else
stream << '"' << create_escapes(raw) << '"';
}
这基本上恢复了一些预定义的类型信息丢失。您可以在 Boost 的 json 输出函数的修改版本中使用它:
void writeJson(std::ostream& stream, const ptree& pt, int indent = 0)
{
static const auto indentStr = [](int level) { return std::string(4 * level, ' '); };
if (indent > 0 && pt.empty())
writeJsonValue(stream, pt);
else if (indent > 0 && pt.count(std::string()) == pt.size()) {
stream << "[\n";
for (auto it = pt.begin(); it != pt.end(); ++it) {
stream << indentStr(indent + 1);
writeJson(stream, it->second, indent + 1);
if (boost::next(it) != pt.end())
stream << ',';
stream << '\n';
}
stream << indentStr(indent) << ']';
} else {
stream << "{\n";
for (auto it = pt.begin(); it != pt.end(); ++it) {
stream << indentStr(indent + 1);
stream << '"' << create_escapes(it->first) << "\": ";
writeJson(stream, it->second, indent + 1);
if (boost::next(it) != pt.end())
stream << ',';
stream << '\n';
}
stream << indentStr(indent) << '}';
}
}
为您的数据调用它,例如作为
writeJson(std::cout, proot);
输出应该是
{
"Number": 5
}
我成功地尝试了类似的事情,并且它们在没有任何黑客攻击的情况下运行良好,请在此处查看我的方法:
Why does Boost property tree write_json save everything as string? Is it possible to change that?
它需要一些努力(您必须提供自己的 JSON-writer 并专门化 reader 的某些部分)但总的来说这是值得的,因为您还将观察到性能获得很多场景。
我在项目中使用 Boost 属性 树时遇到了一个问题。我是这样使用它的:
using Namespace boost::property_tree;
ptree proot;
int myInt = 5;
proot.put("Number", myInt);
write_json("myjson.json", proot);
如果我这样使用它,安全的数据类型是字符串,而不是整数。我的意思的一个例子:
{ "Number": "5" } //what i get
{ "Number": 5 } //what i want
有办法改变吗?
不,你不能改变这种行为,因为字符串值类型已经融入 boost::property_tree
。虽然从技术上讲,您可以使用与默认参数不同的模板类型参数,但您丢失了进入该库的大部分转换逻辑。
作为一个有点古怪的替代方案,请考虑以下内容。
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
using namespace boost::property_tree;
using boost::property_tree::json_parser::create_escapes;
void writeJsonValue(std::ostream& stream, const ptree& pt)
{
const auto raw = pt.get_value<std::string>();
if (raw == "true" || raw == "false") {
stream << raw;
return;
}
if (const auto integral = pt.get_value_optional<int>())
stream << *integral;
else
stream << '"' << create_escapes(raw) << '"';
}
这基本上恢复了一些预定义的类型信息丢失。您可以在 Boost 的 json 输出函数的修改版本中使用它:
void writeJson(std::ostream& stream, const ptree& pt, int indent = 0)
{
static const auto indentStr = [](int level) { return std::string(4 * level, ' '); };
if (indent > 0 && pt.empty())
writeJsonValue(stream, pt);
else if (indent > 0 && pt.count(std::string()) == pt.size()) {
stream << "[\n";
for (auto it = pt.begin(); it != pt.end(); ++it) {
stream << indentStr(indent + 1);
writeJson(stream, it->second, indent + 1);
if (boost::next(it) != pt.end())
stream << ',';
stream << '\n';
}
stream << indentStr(indent) << ']';
} else {
stream << "{\n";
for (auto it = pt.begin(); it != pt.end(); ++it) {
stream << indentStr(indent + 1);
stream << '"' << create_escapes(it->first) << "\": ";
writeJson(stream, it->second, indent + 1);
if (boost::next(it) != pt.end())
stream << ',';
stream << '\n';
}
stream << indentStr(indent) << '}';
}
}
为您的数据调用它,例如作为
writeJson(std::cout, proot);
输出应该是
{
"Number": 5
}
我成功地尝试了类似的事情,并且它们在没有任何黑客攻击的情况下运行良好,请在此处查看我的方法:
Why does Boost property tree write_json save everything as string? Is it possible to change that?
它需要一些努力(您必须提供自己的 JSON-writer 并专门化 reader 的某些部分)但总的来说这是值得的,因为您还将观察到性能获得很多场景。