【问题标题】:JSON data processing in c++14 (Boost)c++14 (Boost) 中的 JSON 数据处理
【发布时间】:2021-03-19 14:33:06
【问题描述】:

我是 C++ 新手(我大部分时间都使用嵌入式 c)。我有类似这样的 JSON 数据:

[10, 
"Session" ,
{"currentYear":"2048","accidents":10,"status":"Accepted"}]

我正在尝试处理这些数据:

boost::json::value testVal;
boost::json::error_code ec;
testVal = boost::json::parse(data, ec);

所以我在 testVal 中有多个项目,我需要从 testVal 中获取对象来测试这样的东西:

boost::json::object testObj = testVal.get_object();
if(testObj.at("currentYear") == "2048")
{
// Do Something
}

但我无法获取对象的实例,我要查找的数据在哪里。

知道如何检查(使用 boost::json)currentYear 中的数据是否为 ​​2048 年吗?

感谢您的帮助。

【问题讨论】:

  • testVal 不是一个对象,它是一个数组,数组中的第三个东西就是你要查找的对象
  • 啊啊啊,太感谢了,终于成功了!

标签: c++ json boost c++14


【解决方案1】:

直截了当

Compiler Explorer

for (auto& element : testVal.as_array()) {
    if (!element.is_object())
        continue;
    if (element.as_object()["currentYear"].as_string() == "2048") {
        std::cout << element << std::endl;
    }
}

虽然我建议使用库中的转换工具。 (稍后会添加示例)

value_to

魔术转换有点做作,因为您的输入...未指定。我假设您从数组中过滤了对象,让我们为了好玩而将 Accepted 值不区分大小写和空格解析为某种枚举:

Godbolt

#include <boost/json.hpp>
#include <boost/json/src.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/spirit/home/x3.hpp>
#include <iostream>
namespace json = boost::json;
using boost::adaptors::filtered;

struct Insurance {
    long   currentYear, accidents;
    enum class Status { Accepted, Rejected, Pending } status;

    friend Status tag_invoke(json::value_to_tag<Status>,
                                json::value const& v) {
        using namespace boost::spirit::x3;

        static const struct S : symbols<Status> {
            S() { this->add
                ("accepted", Status::Accepted)
                ("rejected", Status::Rejected)
                ("pending", Status::Pending);
            }
        } _sym;

        Status result;
        auto& str = v.as_string();

        if (not phrase_parse(str.begin(), str.end(), no_case[_sym] >> eoi,
                             space, result))
            throw std::domain_error("Status");
        return result;
    }
    friend Insurance tag_invoke(json::value_to_tag<Insurance>,
                                json::value const& v) {
        auto& o = v.as_object();
        return {
            std::atol(o.at("currentYear").as_string().data()),
            o.at("accidents").as_int64(),
            Status{}
        };
    }
};

json::value make_array(auto&& range) {
    return json::array(range.begin(), range.end());
}

int main() {
    auto data = boost::json::parse(R"(
        [10, 
        "Session",
        {"currentYear":"2048","accidents":10,"status":"Accepted"},
        {"currentYear":"2049","accidents":11,"status":" rejected"},
        {"currentYear":"2050","accidents":12,"status":"Accepted"},
        {"currentYear":"2051","accidents":13,"status":"pendinG"},
        12,
        "Session"
    ]
    )").as_array();

    auto objects = make_array(data | filtered(std::mem_fn(&json::value::is_object)));

    auto vec = json::value_to<std::vector<Insurance>>(objects);

    for (Insurance const& obj : vec) {
        std::cout << "Year: " << obj.currentYear
                  << " Accidents:" << obj.accidents << std::endl;
    }
}

打印

Year: 2048 Accidents:10
Year: 2049 Accidents:11
Year: 2050 Accidents:12
Year: 2051 Accidents:13

【讨论】:

  • 假设你想在任何位置寻找物体,而不是马上去第三个位置
  • OP 没有提供很多假设。
  • 如约添加了一个带有value_to自定义点的励志示例:Godbolt
  • 更新了示例以更好地展示批量转换godbolt.org/z/nPvq3K
  • @VinnieFalco Lukcily godbolt.org/z/dzjWeo9oT 已经是这样了(参见静态断言)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-16
  • 2016-03-02
  • 1970-01-01
  • 2010-11-12
  • 2020-07-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多