我一直在尝试太多时间,无法从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)):
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); }