问题描述
{
"level_1" :
{
"level_1_1" : [[1,"text",1,2],[2,3,4],[3,5,6,8],[7,4,3]
],"level_1_2" : [[....]],"level_1_3" : [[....]]
}
}
我想获取内容 get_child(level_1.level_1_1)
并将其放入std::map<int,struct json_data>
,其中
struct json_data {
std::string str;
int num1,num2,num3;
};
我该怎么做?
解决方法
请不要像使用 JSON 库一样使用属性树。
在 boost 1.75 中你可以使用 Boost Json:
提升 Json
Boost Json 允许您使用 value_to<T>
进行自动转换。使用 tag_invoke
:
struct json_data {
std::string str;
int64_t num1,num2,num3;
//for json input
friend json_data tag_invoke(json::value_to_tag<json_data>,json::value const& v) {
auto& arr = v.as_array();
return {
value_to<std::string>(arr[1]),//std::string(s.data(),s.size()),arr[2].as_int64(),arr[3].as_int64(),arr[4].as_int64()
};
}
};
现在你可以“只是”阅读它:
auto doc = json::parse(json_text);
using SubLevel = std::vector<json_data>;
using Level = std::map<std::string,SubLevel>;
auto level_1 = json::value_to<Level>(doc.as_object()["level_1"]);
它只是有效。你可以更进一步,解析整个文件:
using File = std::map<std::string,Level>;
auto all = json::value_to<File>(doc);
fmt::print("Whole file: {}\n",fmt::join(all,"\n"));
现场演示
Live On Compiler Explorer
#include <boost/json.hpp>
#include <boost/json/src.hpp> // for header only
#include <iostream>
#include <iomanip>
#include <fmt/ranges.h>
#include <fmt/ostream.h>
namespace json = boost::json;
struct json_data {
std::string str;
int64_t num1,num3;
//for json input
friend json_data tag_invoke(json::value_to_tag<json_data>,json::value const& v) {
auto& arr = v.as_array();
return {
value_to<std::string>(arr[1]),arr[4].as_int64()
};
}
//for debug output
friend std::ostream& operator<<(std::ostream& os,json_data const& jd) {
return os << '{' << std::quoted(jd.str) << ';' << jd.num1 << ';'
<< jd.num2 << ';' << jd.num3 << '}';
}
};
extern std::string const json_text;
int main() {
auto doc = json::parse(json_text);
using SubLevel = std::vector<json_data>;
using Level = std::map<std::string,SubLevel>;
auto level_1 = json::value_to<Level>(doc.as_object()["level_1"]);
fmt::print("Level 1: {}\n",fmt::join(level_1,"\n\t - "));
using File = std::map<std::string,Level>;
auto all = json::value_to<File>(doc);
fmt::print("Whole file: {}\n",all);
}
std::string const json_text = R"(
{
"level_1": {
"level_1_1": [
[1,"text",1,2],[2,3,4],[3,5,6,8],[7,4,3]],"level_1_2": [
[9,8,9,10],[10,11,12],[11,13,14,16],[15,12,11]],"level_1_3": [
[17,16,17,18],[18,19,20],[19,21,22,24],[23,20,19]]
}
})";
印刷品
Level 1: ("level_1_1",{{"text";0;1;2},{"text";1;3;4},{"text";5;6;8},{"text";5;4;3}})
- ("level_1_2",{{"text";8;9;10},{"text";9;11;12},{"text";13;14;16},{"text";13;12;
11}})
- ("level_1_3",{{"text";16;17;18},{"text";17;19;20},{"text";21;22;24},{"text";21;
20;19}})
Whole file: ("level_1",{("level_1_1",{"text
";5;4;3}}),("level_1_2",{"text";13;12
;11}}),("level_1_3",{"text";21;20;
19}})})
提升属性树
如果必须,您可以尝试使用 Boost 属性树来接近:
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include <boost/property_tree/json_parser.hpp>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <fmt/ranges.h>
#include <fmt/ostream.h>
using boost::property_tree::ptree;
struct json_data {
std::string str;
int num1,num3;
friend void read_tree(ptree const& pt,std::vector<json_data>& into) {
auto r = pt.equal_range("");
for (;r.first != r.second; ++r.first) {
read_tree(r.first->second,into.emplace_back());
}
}
friend void read_tree(ptree const& pt,json_data& into) {
auto r = pt.equal_range("");
assert(std::distance(r.first,r.second) == 5);
auto it = r.first;
into = {
(++it)->second.get_value<std::string>(),(++it)->second.get_value<int>(),(++it)->second.get_value<int>()
};
}
//for debug output
friend std::ostream& operator<<(std::ostream& os,json_data const& jd) {
return os << '{' << std::quoted(jd.str) << ';' << jd.num1 << ';'
<< jd.num2 << ';' << jd.num3 << '}';
}
};
extern std::string const json_text;
int main() {
ptree pt;
{
std::istringstream iss(json_text);
read_json(iss,pt);
}
std::vector<json_data> level_1;
read_tree(pt.get_child("level_1.level_1_2"),level_1);
fmt::print("level_1: {}\n","\n\t - "));
}
std::string const json_text = R"(
{
"level_1": {
"level_1_1": [
[1,19]]
}
})";
印刷品
level_1: {"text";8;9;10}
- {"text";9;11;12}
- {"text";13;14;16}
- {"text";13;12;11}
印刷品
Level 1:
- {"text";8;9;10}
- {"text";9;11;12}
- {"text";13;14;16}
- {"text";13;12;11}