发出 YAML 遍历 boost 属性 树(递归地)
Emit YAML iterating through boost property tree (recursively)
我有一个小而复杂的树结构。使用 boost 属性 树作为容器,我试图遍历树并随后使用 yaml-cpp 库将其发送到 yaml 文件。
例如,我有一个嵌套的小 属性 树:
fibonacci:
type: series
entities:
golden_ratio:
ratio: 2.3
function:
power_series: 2
我希望我的 yaml 文件看起来完全像这样。
我写了一个递归函数来遍历树并发送到 yaml。
//Member variable
YAML::Emitter m_out
void iterator(const boost::property_tree::ptree& tree, const std::string& key)
{
for (const auto& item: tree)
{
if (item.second.data().empty()) //check if map node
{
m_out << YAML::BeginMap;
m_out << YAML::Key << item.first;
}
else if (!item.second.data().empty()) //else it is key/value pair
{
m_out << YAML::Key << item.first;
m_out << YAML::Value << item.second.data();
}
if (!item.second.empty()) //If the node has child
{
iterator(item.second, item.first);
}
}
}
我调用函数时使用空键 iterator(root, "")
。我知道 属性 树作为 key/value 对工作,而 Yaml-cpp 具有节点名称。在代码中,我只是试图根据值假设树节点的类型(无值 - 地图节点,否则 - key/value 节点)
显然,我发出的 yaml 文件不具备上述所需的树结构,因为我的逻辑是错误的。我想制作一个递归函数,它可以遍历任何类型的树并将其发送到 yaml 文件。
是否可以迭代树并随后递归地发送到 yaml?如果是,我将不胜感激。
所以我采用了您想要的 YAML 并将其通过 online converter 以获得 "reliable" ptree 表示(有趣的是,您将其排除在问题之外)。
然后我继续进行简单的 ptree 往返以进行完整性检查:
#include <boost/property_tree/json_parser.hpp>
#include <iostream>
using boost::property_tree::ptree;
std::istringstream sample_json();
ptree sample_ptree();
int main() {
write_json(std::cout, sample_ptree());
}
std::istringstream sample_json() {
return std::istringstream(R"({
"fibonacci": {
"type": "series",
"entities": {
"golden_ratio": {
"ratio": 2.3
},
"function": {
"power_series": 2
}
}
}
})");
}
ptree sample_ptree() {
ptree pt;
{
auto stream = sample_json();
read_json(stream, pt);
}
return pt;
}
版画
{
"fibonacci": {
"type": "series",
"entities": {
"golden_ratio": {
"ratio": "2.3"
},
"function": {
"power_series": "2"
}
}
}
}
to_yaml
取#1
最简单的当然是读取相同的JSON,然后让yaml-cpp
进行转换:
auto stream = sample_json();
std::cout << YAML::Load(stream) << "\n";
打印:
{fibonacci: {type: series, entities: {golden_ratio: {ratio: 2.3}, function: {power_series: 2}}}}
to_yaml
拍摄 #2:漂亮的印花
首发
- 命名很重要。
iterator
没有描述功能,并且与 well-known concept from the standard library 冲突
key
参数未使用
- 你只
BeginMap
,如果你在代码中的任何地方都没有 EndMap
,你怎么期待一棵有效的树?
- 请不要使用全局变量。它们使您的代码变得脆弱(非确定性、非幂等、不可重入、非线程安全等)。只需将
Emitter&
作为参数传递即可。
我会让它变得更简单:
void to_yaml(ptree const& node, YAML::Emitter &m_out) {
if (node.empty()) {
m_out << YAML::Value << node.data();
} else {
m_out << YAML::BeginMap;
for (auto const&item : node) {
m_out << YAML::Key << item.first;
to_yaml(item.second, m_out);
}
m_out << YAML::EndMap;
}
}
现在,要有一个方便的入口点,请添加一个重载:
std::string to_yaml(ptree const& tree) {
YAML::Emitter out;
to_yaml(tree, out);
return out.c_str();
}
现在您可以打印结果:
std::cout << to_yaml(sample_ptree()) << "\n";
打印:
fibonacci:
type: series
entities:
golden_ratio:
ratio: 2.3
function:
power_series: 2
完整列表
#include <iostream>
#include <boost/property_tree/json_parser.hpp>
using boost::property_tree::ptree;
std::istringstream sample_json();
ptree sample_ptree();
#include "yaml-cpp/yaml.h"
void to_yaml(ptree const& node, YAML::Emitter &m_out) {
if (node.empty()) {
m_out << YAML::Value << node.data();
} else {
m_out << YAML::BeginMap;
for (auto const&item : node) {
m_out << YAML::Key << item.first;
to_yaml(item.second, m_out);
}
m_out << YAML::EndMap;
}
}
std::string to_yaml(ptree const& tree) {
YAML::Emitter out;
to_yaml(tree, out);
return out.c_str();
}
int main() {
write_json(std::cout, sample_ptree());
{
auto stream = sample_json();
std::cout << YAML::Load(stream) << "\n";
}
std::cout << to_yaml(sample_ptree()) << "\n";
}
std::istringstream sample_json() {
return std::istringstream(R"({
"fibonacci": {
"type": "series",
"entities": {
"golden_ratio": {
"ratio": 2.3
},
"function": {
"power_series": 2
}
}
}
})");
}
ptree sample_ptree() {
ptree pt;
{
auto stream = sample_json();
read_json(stream, pt);
}
return pt;
}
我有一个小而复杂的树结构。使用 boost 属性 树作为容器,我试图遍历树并随后使用 yaml-cpp 库将其发送到 yaml 文件。
例如,我有一个嵌套的小 属性 树:
fibonacci:
type: series
entities:
golden_ratio:
ratio: 2.3
function:
power_series: 2
我希望我的 yaml 文件看起来完全像这样。
我写了一个递归函数来遍历树并发送到 yaml。
//Member variable
YAML::Emitter m_out
void iterator(const boost::property_tree::ptree& tree, const std::string& key)
{
for (const auto& item: tree)
{
if (item.second.data().empty()) //check if map node
{
m_out << YAML::BeginMap;
m_out << YAML::Key << item.first;
}
else if (!item.second.data().empty()) //else it is key/value pair
{
m_out << YAML::Key << item.first;
m_out << YAML::Value << item.second.data();
}
if (!item.second.empty()) //If the node has child
{
iterator(item.second, item.first);
}
}
}
我调用函数时使用空键 iterator(root, "")
。我知道 属性 树作为 key/value 对工作,而 Yaml-cpp 具有节点名称。在代码中,我只是试图根据值假设树节点的类型(无值 - 地图节点,否则 - key/value 节点)
显然,我发出的 yaml 文件不具备上述所需的树结构,因为我的逻辑是错误的。我想制作一个递归函数,它可以遍历任何类型的树并将其发送到 yaml 文件。 是否可以迭代树并随后递归地发送到 yaml?如果是,我将不胜感激。
所以我采用了您想要的 YAML 并将其通过 online converter 以获得 "reliable" ptree 表示(有趣的是,您将其排除在问题之外)。
然后我继续进行简单的 ptree 往返以进行完整性检查:
#include <boost/property_tree/json_parser.hpp>
#include <iostream>
using boost::property_tree::ptree;
std::istringstream sample_json();
ptree sample_ptree();
int main() {
write_json(std::cout, sample_ptree());
}
std::istringstream sample_json() {
return std::istringstream(R"({
"fibonacci": {
"type": "series",
"entities": {
"golden_ratio": {
"ratio": 2.3
},
"function": {
"power_series": 2
}
}
}
})");
}
ptree sample_ptree() {
ptree pt;
{
auto stream = sample_json();
read_json(stream, pt);
}
return pt;
}
版画
{
"fibonacci": {
"type": "series",
"entities": {
"golden_ratio": {
"ratio": "2.3"
},
"function": {
"power_series": "2"
}
}
}
}
to_yaml
取#1
最简单的当然是读取相同的JSON,然后让yaml-cpp
进行转换:
auto stream = sample_json();
std::cout << YAML::Load(stream) << "\n";
打印:
{fibonacci: {type: series, entities: {golden_ratio: {ratio: 2.3}, function: {power_series: 2}}}}
to_yaml
拍摄 #2:漂亮的印花
首发
- 命名很重要。
iterator
没有描述功能,并且与 well-known concept from the standard library 冲突
key
参数未使用- 你只
BeginMap
,如果你在代码中的任何地方都没有EndMap
,你怎么期待一棵有效的树? - 请不要使用全局变量。它们使您的代码变得脆弱(非确定性、非幂等、不可重入、非线程安全等)。只需将
Emitter&
作为参数传递即可。
我会让它变得更简单:
void to_yaml(ptree const& node, YAML::Emitter &m_out) {
if (node.empty()) {
m_out << YAML::Value << node.data();
} else {
m_out << YAML::BeginMap;
for (auto const&item : node) {
m_out << YAML::Key << item.first;
to_yaml(item.second, m_out);
}
m_out << YAML::EndMap;
}
}
现在,要有一个方便的入口点,请添加一个重载:
std::string to_yaml(ptree const& tree) {
YAML::Emitter out;
to_yaml(tree, out);
return out.c_str();
}
现在您可以打印结果:
std::cout << to_yaml(sample_ptree()) << "\n";
打印:
fibonacci:
type: series
entities:
golden_ratio:
ratio: 2.3
function:
power_series: 2
完整列表
#include <iostream>
#include <boost/property_tree/json_parser.hpp>
using boost::property_tree::ptree;
std::istringstream sample_json();
ptree sample_ptree();
#include "yaml-cpp/yaml.h"
void to_yaml(ptree const& node, YAML::Emitter &m_out) {
if (node.empty()) {
m_out << YAML::Value << node.data();
} else {
m_out << YAML::BeginMap;
for (auto const&item : node) {
m_out << YAML::Key << item.first;
to_yaml(item.second, m_out);
}
m_out << YAML::EndMap;
}
}
std::string to_yaml(ptree const& tree) {
YAML::Emitter out;
to_yaml(tree, out);
return out.c_str();
}
int main() {
write_json(std::cout, sample_ptree());
{
auto stream = sample_json();
std::cout << YAML::Load(stream) << "\n";
}
std::cout << to_yaml(sample_ptree()) << "\n";
}
std::istringstream sample_json() {
return std::istringstream(R"({
"fibonacci": {
"type": "series",
"entities": {
"golden_ratio": {
"ratio": 2.3
},
"function": {
"power_series": 2
}
}
}
})");
}
ptree sample_ptree() {
ptree pt;
{
auto stream = sample_json();
read_json(stream, pt);
}
return pt;
}