提升 属性 树 json
boost property tree json
我有一个 JSON 文件:
{
"level_1" :
{
"level_1_1" : [[1, "text", 0, 1, 2],
[2, "text", 1, 3, 4],
[3, "text", 5, 6, 8],
[7, "text", 5, 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"));
现场演示
在编译器资源管理器上运行
#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, 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()
};
}
//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", 0, 1, 2],
[2, "text", 1, 3, 4],
[3, "text", 5, 6, 8],
[7, "text", 5, 4, 3]],
"level_1_2": [
[9, "text", 8, 9, 10],
[10, "text", 9, 11, 12],
[11, "text", 13, 14, 16],
[15, "text", 13, 12, 11]],
"level_1_3": [
[17, "text", 16, 17, 18],
[18, "text", 17, 19, 20],
[19, "text", 21, 22, 24],
[23, "text", 21, 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";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}})})
提升属性树
如果必须,可以尝试使用 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, num2, 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>(),
//std::string(s.data(), s.size()),
(++it)->second.get_value<int>(),
(++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", fmt::join(level_1, "\n\t - "));
}
std::string const json_text = R"(
{
"level_1": {
"level_1_1": [
[1, "text", 0, 1, 2],
[2, "text", 1, 3, 4],
[3, "text", 5, 6, 8],
[7, "text", 5, 4, 3]],
"level_1_2": [
[9, "text", 8, 9, 10],
[10, "text", 9, 11, 12],
[11, "text", 13, 14, 16],
[15, "text", 13, 12, 11]],
"level_1_3": [
[17, "text", 16, 17, 18],
[18, "text", 17, 19, 20],
[19, "text", 21, 22, 24],
[23, "text", 21, 20, 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}
我有一个 JSON 文件:
{
"level_1" :
{
"level_1_1" : [[1, "text", 0, 1, 2],
[2, "text", 1, 3, 4],
[3, "text", 5, 6, 8],
[7, "text", 5, 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"));
现场演示
在编译器资源管理器上运行
#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, 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()
};
}
//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", 0, 1, 2],
[2, "text", 1, 3, 4],
[3, "text", 5, 6, 8],
[7, "text", 5, 4, 3]],
"level_1_2": [
[9, "text", 8, 9, 10],
[10, "text", 9, 11, 12],
[11, "text", 13, 14, 16],
[15, "text", 13, 12, 11]],
"level_1_3": [
[17, "text", 16, 17, 18],
[18, "text", 17, 19, 20],
[19, "text", 21, 22, 24],
[23, "text", 21, 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";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}})})
提升属性树
如果必须,可以尝试使用 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, num2, 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>(),
//std::string(s.data(), s.size()),
(++it)->second.get_value<int>(),
(++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", fmt::join(level_1, "\n\t - "));
}
std::string const json_text = R"(
{
"level_1": {
"level_1_1": [
[1, "text", 0, 1, 2],
[2, "text", 1, 3, 4],
[3, "text", 5, 6, 8],
[7, "text", 5, 4, 3]],
"level_1_2": [
[9, "text", 8, 9, 10],
[10, "text", 9, 11, 12],
[11, "text", 13, 14, 16],
[15, "text", 13, 12, 11]],
"level_1_3": [
[17, "text", 16, 17, 18],
[18, "text", 17, 19, 20],
[19, "text", 21, 22, 24],
[23, "text", 21, 20, 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}