当前位置: 首页 > 面试题库 >

boost :: ptree找到吗?或如何访问深层阵列?C ++

祁雪峰
2023-03-14
问题内容

我一直在尝试太多时间,无法从boost库访问json_reader ptree。

我有一个经常封装的json文件:(pseudo-json :)

"Foo": {
  "nameofFoo:"foofoo"
  "Bar": [{
    "BarFoo": 
      { BarFooDeep: { 
           BarFooDeepDeep: { 
            "BarFooValue1": 123 
            "BarFooValue2" : 456
          }
        }
      }
     "FooBar": [ {
        "FooBarDeep" :[ {
           FooBarDeepDeep:[ {
              FooBarValue1: "ineedthis"
              FooBarValue2: "andthis"
              } ]
           FooBarDeepDeep1:[ {
              FooBarValue1: "ineedthis"
              FooBarValue2: "andthis"
              } ]
        "FooBarDeep" :[ {
           FooBarDeepDeep2:[ {
              FooBarValue1: "ineedthis"
              FooBarValue2: "andthis"
              } ]
           FooBarDeepDeep3:[ {
              FooBarValue1: "ineedthis"
              FooBarValue2: "andthis"
              } ]
and so on .... won t complete this now...

现在,我只需要获取所有FooBar的FooBarValue1和FooBarValue2即可。

我知道ptree将数组与空子元素(“”)放在一起

我可以通过递归地遍历所有子项来访问所有成员。

但是,有没有更好的方法来访问特殊值?

ptree查找如何工作?我总是得到编译器错误…

ptree jsonPT;
read_json( JSON_PATH, jsonPT);
ptree::const_iterator myIT = jsonPT.find("FooBarValue1");
double mlat = boost::lexical_cast<int>(myIT->second.data());

错误:从’boost :: property_tree :: basic_ptree,std :: basic_string> ::
assoc_iterator’转换为非标量类型’boost :: property_tree :: basic_ptree,std ::
basic_string> :: const_iterator’请求的ptree :: const_iterator myIT =
jsonPT.find(“ FooBarValue1”);

谁能给我一个有用的提示,如何访问此ptree ?!


问题答案:

您可以编写自己的“选择器”查询,因此可以编写以下内容:

read_json("input.txt", pt);

std::ostream_iterator<std::string> out(std::cout, ", ");

std::cout << "\nSpecific children but in arrays: ";
enumerate_path(pt, "Foo.Bar..FooBar..FooBarDeep1..FooBarDeepDeep6..FooBarValue2", out);

std::cout << "\nSingle wildcard: ";
enumerate_path(pt, "Foo.Bar..FooBar..FooBarDeep1..*..FooBarValue2", out);

std::cout << "\nTwo wildcards: ";
enumerate_path(pt, "Foo.Bar..FooBar..*..*..FooBarValue2", out);

enumerate_path函数不必太复杂,不需要任何输出迭代器(因此您也可以back_inserter(some_vector)):

template <typename Tree, typename Out, typename T = std::string>
Out enumerate_path(Tree const& pt, typename Tree::path_type path, Out out) {
    if (path.empty())
        return out;

    if (path.single()) {
        *out++ = pt.template get<T>(path);
    } else {
        auto head = path.reduce();
        for (auto& child : pt) {
            if (head == "*" || child.first == head) {
                out = enumerate_path(child.second, path, out);
            }
        }
    }

    return out;
}

作为简单的工作演示打印:

Specific children but in arrays: andthis6, 
Single wildcard: andthis6, andthis7, andthis8, andthis9, 
Two wildcards: andthis1, andthis2, andthis3, andthis4, andthis6, andthis7, andthis8, andthis9,

那就是下面的input.txt:

{
    "Foo": {
        "nameofFoo": "foofoo",
        "Bar": [{
            "BarFoo": {
                "BarFooDeep": {
                    "BarFooDeepDeep": {
                        "BarFooValue1": 123,
                        "BarFooValue2": 456
                    }
                }
            },
            "FooBar": [{
                "FooBarDeep0": [{
                    "FooBarDeepDeep1": [{
                        "FooBarValue1": "ineedthis1",
                        "FooBarValue2": "andthis1"
                    }],
                    "FooBarDeepDeep2": [{
                        "FooBarValue1": "ineedthis2",
                        "FooBarValue2": "andthis2"
                    }]
                },
                {
                    "FooBarDeepDeep3": [{
                        "FooBarValue1": "ineedthis3",
                        "FooBarValue2": "andthis3"
                    }],
                    "FooBarDeepDeep4": [{
                        "FooBarValue1": "ineedthis4",
                        "FooBarValue2": "andthis4"
                    }]
                }],
                "FooBarDeep1": [{
                    "FooBarDeepDeep6": [{
                        "FooBarValue1": "ineedthis6",
                        "FooBarValue2": "andthis6"
                    }],
                    "FooBarDeepDeep7": [{
                        "FooBarValue1": "ineedthis7",
                        "FooBarValue2": "andthis7"
                    }]
                },
                {
                    "FooBarDeepDeep8": [{
                        "FooBarValue1": "ineedthis8",
                        "FooBarValue2": "andthis8"
                    }],
                    "FooBarDeepDeep9": [{
                        "FooBarValue1": "ineedthis9",
                        "FooBarValue2": "andthis9"
                    }]
                }]
            }]
        }]
    }
}

[Live On Coliru](http://coliru.stacked-crooked.com/a/2a57e51a163150f6)

完整清单

[Live On Coliru](http://coliru.stacked-crooked.com/a/75719ffb76659264)

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <iostream>

template <typename Tree, typename Out, typename T = std::string>
Out enumerate_path(Tree const& pt, typename Tree::path_type path, Out out) {
    if (path.empty())
        return out;

    if (path.single()) {
        *out++ = pt.template get<T>(path);
    } else {
        auto head = path.reduce();
        for (auto& child : pt) {
            if (head == "*" || child.first == head) {
                out = enumerate_path(child.second, path, out);
            }
        }
    }

    return out;
}

int main() {

    std::ostream_iterator<std::string> out(std::cout, ", ");
    using namespace boost::property_tree;

    ptree pt;
    read_json("input.txt", pt);

    std::cout << "\nSpecific children but in arrays: ";
    enumerate_path(pt, "Foo.Bar..FooBar..FooBarDeep1..FooBarDeepDeep6..FooBarValue2", out);

    std::cout << "\nSingle wildcard: ";
    enumerate_path(pt, "Foo.Bar..FooBar..FooBarDeep1..*..FooBarValue2", out);

    std::cout << "\nTwo wildcards: ";
    enumerate_path(pt, "Foo.Bar..FooBar..*..*..FooBarValue2", out);
}


 类似资料:
  • 我正在读取xml文件并将其存储到boost::property_tree::ptree pt(object)中。 我试图序列化这个ptree对象使用方法定义在ptree_serialization.hpp 当我使用上述代码时,我得到的错误是:; 如果我做错了什么,你能告诉我吗。请告诉我是否可以序列化xml解析的属性ptree对象。

  • 我有以下数组,当我做,我得到: 我尝试按如下方式访问阵列: 但这让我明白: 未定义的0 注: 我从Facebook SDK 4中获得了这个数组,所以我不知道最初的数组结构。 作为示例,我如何访问值来自阵列?

  • 问题内容: 它的程序基本从用户那里输入6个数字,将它们存储在一个数组中,计算它们的均值和众数。还计算多少个数字大于平均值。我程序的代码是我错的地方 我的意思是正确的,但是我在模式上有问题。 包p18; 导入java.util.Arrays; 导入java.util.Scanner; 问题答案: 您根本没有将输入存储到数组中。您需要添加类似以下内容的内容来存储用户输入: 我还将平均值和总数更改为双精

  • 问题内容: 我对列表副本有一些问题: 所以之后我得到了E0来自,我做的副本E0通过调用。我猜这里是的较深的副本E0,我通过。但是在主要功能上。 为什么循环之前的结果与for循环之后的结果不同? 下面是我的代码: 问题答案: 不是深层副本。你不使用做出深层副本两者并很浅拷贝)。 你用于深度复制列表。 请参阅以下代码段 现在看deepcopy操作

  • 问题内容: 我在SASS中有一个列表,并且我正在尝试使用方括号表示法访问这些项目: 但这给了我一个错误。 还有其他方法吗? 我为什么要这样做? 我有一个颜色列表,必须根据服务器分配给它们的颜色在不同的元素上进行设置。标记已编号的类(,等)。这是我的目标CSS: 我想不用手工编写所有内容,而是可以将SASS集合与循环一起使用: 但这只是给我以下错误: 语法错误:“ … color-collectio

  • 我一直在使用字节好友来监控应用程序的行为,我想在执行特定方法之前检查其中一个应用程序类的数组字段是否已更新。我已经阅读了字节好友留档和堆栈溢出问题,并找到了一些有用的留档,了解如何使用拦截字段访问。 然而,因为我感兴趣的领域是一个数组,中的和事件似乎无关紧要。 是否可以使用ByteBuddy跟踪数组字段的更新?