在 C++ 中获取嵌套 JSON 数组和矩阵
Getting nested JSON arrays and matrices in C++
我必须使用 C++ 从 JSON 文件中读取一些数据。经过一些研究,我发现 Boost 属性 Tree 是最受推荐的方法,我能够将它和 运行 简单的字符串结合起来。但是,当涉及到深层嵌套数组和矩阵时,我找不到适合我的解决方案。
这就是我的 JSON 文件的样子。可以有多个 "objects" 每个数据:
{
"some_data":
{
(...)
},
"objects": [
{
"name": "Some name",
"id": 0,
"array": [ 1.9352999925613403, -1.0619000196456909, 38.685501098632813 ],
"matrix": [
[ -0.74119997024536133, -0.56959998607635498, 0.35519999265670776, 0 ],
[ 0.61210000514984131, -0.35649999976158142, 0.70579999685287476, 0 ],
[ 0.27540001273155212, -0.74059998989105225, -0.6129000186920166, 0 ],
[ 1.9352999925613403, -1.0619000196456909, 38.685501098632813, 1 ]
],
(...)
},
(...)
]
}
我使用以下代码成功检索存储在字符串 "name" 中的数据(两个循环都工作正常):
#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/foreach.hpp>
int main() {
boost::property_tree::ptree root;
boost::property_tree::read_json("dataFile.json", root);
std::string name;
BOOST_FOREACH(boost::property_tree::ptree::value_type& v, root.get_child("objects")) {
name = v.second.get<std::string>("name");
}
for(boost::property_tree::ptree::value_type& v : root.get_child("objects")) {
name = v.second.get<std::string>("name");
}
return 0;
}
是否有类似的方法或对我的代码进行一些扩展,使我能够获取数组和矩阵的值?我无法在迭代 "objects" 的循环中嵌套另一个 for(each) 循环,但也无法立即获取数组或矩阵数据。
提前感谢您的帮助!
就像我在评论中警告的那样,Boost 属性 Tree 不是 JSON 库。这并不意味着你在这里要求的是不可能的。
有可能。让我们选择 Array
和 Matrix
定义:
using Array = std::array<double, 3>;
using Matrix = std::array<std::array<double, 4>, 4>;
我的首选策略(而不是使用来自 属性 Tree 的 Translators 框架)是编写程序助手:
void read(ptree const& pt, double& into);
void read(ptree const& pt, Array& into);
void read(ptree const& pt, Matrix& into);
事实上,我们可以在同一个实现中捕获两者 Array/Matrix:
void read(ptree const& pt, double& into) {
into = pt.get_value<double>();
}
template <typename ArrayOrMatrix>
void read(ptree const& pt, ArrayOrMatrix& into) {
auto elements = pt.equal_range(""); // unnamed elements
assert(boost::size(elements) == into.size());
auto out = into.begin();
for (auto& [_,v] : boost::make_iterator_range(elements)) {
read(v, *out++);
}
}
现在我们可以简单地把我们的程序写成:
boost::property_tree::ptree pt;
read_json(iss, pt);
for (auto& [_,obj] : pt.get_child("objects")) {
std::cout << "Reading object " << std::quoted(obj.get<std::string>("name")) << "\n";
Array a;
Matrix m;
read(obj.get_child("array"), a);
read(obj.get_child("matrix"), m);
}
#include <boost/property_tree/json_parser.hpp>
#include <iostream>
#include <iomanip>
#include <cassert>
using boost::property_tree::ptree;
using Array = std::array<double, 3>;
using Matrix = std::array<std::array<double, 4>, 4>;
void read(ptree const& pt, double& into) {
into = pt.get_value<double>();
}
template <typename ArrayOrMatrix>
void read(ptree const& pt, ArrayOrMatrix& into) {
auto elements = pt.equal_range(""); // unnamed elements
assert(boost::size(elements) == into.size());
auto out = into.begin();
for (auto& [_,v] : boost::make_iterator_range(elements)) {
read(v, *out++);
}
}
int main() {
std::istringstream iss(R"({
"some_data":
{
},
"objects": [
{
"name": "Some name",
"id": 0,
"array": [ 1.9352999925613403, -1.0619000196456909, 38.685501098632813 ],
"matrix": [
[ -0.74119997024536133, -0.56959998607635498, 0.35519999265670776, 0 ],
[ 0.61210000514984131, -0.35649999976158142, 0.70579999685287476, 0 ],
[ 0.27540001273155212, -0.74059998989105225, -0.6129000186920166, 0 ],
[ 1.9352999925613403, -1.0619000196456909, 38.685501098632813, 1 ]
],
"more": {}
}
]
})");
boost::property_tree::ptree pt;
read_json(iss, pt);
for (auto& [_,obj] : pt.get_child("objects")) {
std::cout << "Reading object " << std::quoted(obj.get<std::string>("name")) << "\n";
Array a;
Matrix m;
read(obj.get_child("array"), a);
read(obj.get_child("matrix"), m);
}
//write_json(std::cout, pt);
}
打印:
Reading object "Some name"
我必须使用 C++ 从 JSON 文件中读取一些数据。经过一些研究,我发现 Boost 属性 Tree 是最受推荐的方法,我能够将它和 运行 简单的字符串结合起来。但是,当涉及到深层嵌套数组和矩阵时,我找不到适合我的解决方案。
这就是我的 JSON 文件的样子。可以有多个 "objects" 每个数据:
{
"some_data":
{
(...)
},
"objects": [
{
"name": "Some name",
"id": 0,
"array": [ 1.9352999925613403, -1.0619000196456909, 38.685501098632813 ],
"matrix": [
[ -0.74119997024536133, -0.56959998607635498, 0.35519999265670776, 0 ],
[ 0.61210000514984131, -0.35649999976158142, 0.70579999685287476, 0 ],
[ 0.27540001273155212, -0.74059998989105225, -0.6129000186920166, 0 ],
[ 1.9352999925613403, -1.0619000196456909, 38.685501098632813, 1 ]
],
(...)
},
(...)
]
}
我使用以下代码成功检索存储在字符串 "name" 中的数据(两个循环都工作正常):
#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/foreach.hpp>
int main() {
boost::property_tree::ptree root;
boost::property_tree::read_json("dataFile.json", root);
std::string name;
BOOST_FOREACH(boost::property_tree::ptree::value_type& v, root.get_child("objects")) {
name = v.second.get<std::string>("name");
}
for(boost::property_tree::ptree::value_type& v : root.get_child("objects")) {
name = v.second.get<std::string>("name");
}
return 0;
}
是否有类似的方法或对我的代码进行一些扩展,使我能够获取数组和矩阵的值?我无法在迭代 "objects" 的循环中嵌套另一个 for(each) 循环,但也无法立即获取数组或矩阵数据。
提前感谢您的帮助!
就像我在评论中警告的那样,Boost 属性 Tree 不是 JSON 库。这并不意味着你在这里要求的是不可能的。
有可能。让我们选择 Array
和 Matrix
定义:
using Array = std::array<double, 3>;
using Matrix = std::array<std::array<double, 4>, 4>;
我的首选策略(而不是使用来自 属性 Tree 的 Translators 框架)是编写程序助手:
void read(ptree const& pt, double& into);
void read(ptree const& pt, Array& into);
void read(ptree const& pt, Matrix& into);
事实上,我们可以在同一个实现中捕获两者 Array/Matrix:
void read(ptree const& pt, double& into) {
into = pt.get_value<double>();
}
template <typename ArrayOrMatrix>
void read(ptree const& pt, ArrayOrMatrix& into) {
auto elements = pt.equal_range(""); // unnamed elements
assert(boost::size(elements) == into.size());
auto out = into.begin();
for (auto& [_,v] : boost::make_iterator_range(elements)) {
read(v, *out++);
}
}
现在我们可以简单地把我们的程序写成:
boost::property_tree::ptree pt;
read_json(iss, pt);
for (auto& [_,obj] : pt.get_child("objects")) {
std::cout << "Reading object " << std::quoted(obj.get<std::string>("name")) << "\n";
Array a;
Matrix m;
read(obj.get_child("array"), a);
read(obj.get_child("matrix"), m);
}
#include <boost/property_tree/json_parser.hpp>
#include <iostream>
#include <iomanip>
#include <cassert>
using boost::property_tree::ptree;
using Array = std::array<double, 3>;
using Matrix = std::array<std::array<double, 4>, 4>;
void read(ptree const& pt, double& into) {
into = pt.get_value<double>();
}
template <typename ArrayOrMatrix>
void read(ptree const& pt, ArrayOrMatrix& into) {
auto elements = pt.equal_range(""); // unnamed elements
assert(boost::size(elements) == into.size());
auto out = into.begin();
for (auto& [_,v] : boost::make_iterator_range(elements)) {
read(v, *out++);
}
}
int main() {
std::istringstream iss(R"({
"some_data":
{
},
"objects": [
{
"name": "Some name",
"id": 0,
"array": [ 1.9352999925613403, -1.0619000196456909, 38.685501098632813 ],
"matrix": [
[ -0.74119997024536133, -0.56959998607635498, 0.35519999265670776, 0 ],
[ 0.61210000514984131, -0.35649999976158142, 0.70579999685287476, 0 ],
[ 0.27540001273155212, -0.74059998989105225, -0.6129000186920166, 0 ],
[ 1.9352999925613403, -1.0619000196456909, 38.685501098632813, 1 ]
],
"more": {}
}
]
})");
boost::property_tree::ptree pt;
read_json(iss, pt);
for (auto& [_,obj] : pt.get_child("objects")) {
std::cout << "Reading object " << std::quoted(obj.get<std::string>("name")) << "\n";
Array a;
Matrix m;
read(obj.get_child("array"), a);
read(obj.get_child("matrix"), m);
}
//write_json(std::cout, pt);
}
打印:
Reading object "Some name"