簡體   English   中英

獲取嵌套 JSON arrays 和 C++ 中的矩陣

[英]Getting nested JSON arrays and matrices in C++

我必須使用 C++ 從 JSON 文件中讀取一些數據。 經過一些研究,我發現 Boost Property Tree 是最推薦的方法,並且我能夠使用簡單的字符串啟動並運行它。 但是,當涉及到深層嵌套 arrays 和矩陣時,我沒有找到適合我的解決方案。

這就是我的 JSON 文件的樣子。 可以有多個“對象”及其數據:

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

是否有類似的方法或對我的代碼進行一些擴展以允許我獲取數組和矩陣的值? 我無法在遍歷“對象”的循環中嵌套另一個 for(each) 循環,但也無法一次獲取數組或矩陣數據。

感謝您提前提供任何幫助!

就像我在評論中警告的那樣,Boost Property Tree 不是 JSON 庫。 這並不意味着您在這里要求的內容是不可能的。

有可能的。 讓我們選擇ArrayMatrix定義:

using Array = std::array<double, 3>;
using Matrix = std::array<std::array<double, 4>, 4>;

我首選的策略(而不是使用 Property 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);
}

在 Coliru 現場觀看

#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"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM