本文介绍了boost::ptree 找到了吗?或者如何访问深数组?C++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试从 boost 库中访问一个 json_reader ptree.

我有一个经常被封装的json文件:(伪json:)

"Foo": {"foo 名:"foofoo"酒吧": [{BarFoo":{ BarFooDeep:{BarFooDeepDeep:{BarFooValue1":123BarFooValue2":456}}}"FooBar": [ {FooBarDeep":[{FooBarDeepDeep:[ {FooBarValue1:ineedthis"FooBarValue2: "andthis"]]FooBarDeepDeep1:[ {FooBarValue1:ineedthis"FooBarValue2: "andthis"]]FooBarDeep":[{FooBarDeepDeep2:[ {FooBarValue1:ineedthis"FooBarValue2: "andthis"]]FooBarDeepDeep3:[ {FooBarValue1:ineedthis"FooBarValue2: "andthis"]]等等......现在不会完成这个......

现在我只需要获取所有 FooBar 的 FooBarValue1 和 FooBarValue2.

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

我可以通过递归遍历所有孩子来访问所有成员.

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

ptree find 是如何工作的?我总是收到编译器错误...

ptree jsonPT;read_json( JSON_PATH, jsonPT);ptree::const_iterator myIT = jsonPT.find("FooBarValue1");double mlat = boost::lexical_cast(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?!?

解决方案

正如我评论的链接答案中所暗示的 (Boost.PropertyTree 子路径处理),您可以编写自己的选择器"查询,因此您可以编写如下内容:

read_json("input.txt", pt);std::ostream_iteratorout(std::cout, ", ");std::cout <<"
特定的孩子,但在数组中:";enumerate_path(pt, "Foo.Bar..FooBar..FooBarDeep1..FooBarDeepDeep6..FooBarValue2", out);std::cout <<"
单个通配符:";enumerate_path(pt, "Foo.Bar..FooBar..FooBarDeep1..*..FooBarValue2", out);std::cout <<"
两个通配符:";enumerate_path(pt, "Foo.Bar..FooBar..*..*..FooBarValue2", out);

enumerate_path 函数不需要太复杂并且可以接受任何输出迭代器(所以你也可以back_inserter(some_vector)):

template Out enumerate_path(Tree const& pt, typename Tree::path_type path, Out out) {如果(路径.空())返回;如果(路径.单()){*out++ = pt.template get(path);} 别的 {自动头 = path.reduce();for (auto& child : pt) {if (head == "*" || child.first == head) {out = enumerate_path(child.second, path, out);}}}返回;}

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

特定的孩子,但在数组中:andthis6,单个通配符:andthis6,andthis7,andthis8,andthis9,两个通配符:andthis1,andthis2,andthis3,andthis4,andthis6,andthis7,andthis8,andthis9,

即使用以下 input.txt:

{福":{"nameofFoo": "foofoo",酒吧": [{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"}]}]}]}]}}

完整列表

#include #include #include template Out enumerate_path(Tree const& pt, typename Tree::path_type path, Out out) {如果(路径.空())返回;如果(路径.单()){*out++ = pt.template get(path);} 别的 {自动头 = path.reduce();for (auto& child : pt) {if (head == "*" || child.first == head) {out = enumerate_path(child.second, path, out);}}}返回;}int main() {std::ostream_iteratorout(std::cout, ", ");使用命名空间 boost::property_tree;ptree pt;read_json("input.txt", pt);std::cout <<"
特定的孩子,但在数组中:";enumerate_path(pt, "Foo.Bar..FooBar..FooBarDeep1..FooBarDeepDeep6..FooBarValue2", out);std::cout <<"
单个通配符:";enumerate_path(pt, "Foo.Bar..FooBar..FooBarDeep1..*..FooBarValue2", out);std::cout <<"
两个通配符:";enumerate_path(pt, "Foo.Bar..FooBar..*..*..FooBarValue2", out);}

I have been trying for too much time now, to access a json_reader ptree from the boost library.

I have a json file that is capsulated really often: (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...

Now I only need to get FooBarValue1 and FooBarValue2 of all FooBar.

I know ptree puts arrays together with empty childs ("")

I can access all the members by itereration over all the childs recursively.

But is there not a better way to access special values?

how does ptree find works? i always get compiler errors ...

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

Can anyone give me a useful hint how to get access to this ptree?!?

解决方案

As hinted in the linked answer I commented (Boost.PropertyTree subpath processing), you could write your own "selector" query, so you could write stuff like:

read_json("input.txt", pt);

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

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

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

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

The enumerate_path function need not be too complicated and takes any output iterator (so you can back_inserter(some_vector) just as well):

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;
}

As simple working demo prints:

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

That is with the following 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"
                    }]
                }]
            }]
        }]
    }
}

Full Listing

#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 << "
Specific children but in arrays: ";
    enumerate_path(pt, "Foo.Bar..FooBar..FooBarDeep1..FooBarDeepDeep6..FooBarValue2", out);

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

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

这篇关于boost::ptree 找到了吗?或者如何访问深数组?C++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-01 16:52