Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Parse elements from json array using boost

here is the json I want to parse:

{"jsonrpc":"2.0","method":"subscription","params":{"channel":"book.BTC-PERPETUAL.raw","data":{"type":"change","timestamp":1635513739435,"prev_change_id":6807100702,"instrument_name":"BTC-PERPETUAL","change_id":6807100703,"bids":[["new",60772.0,50.0], "demo"],"asks":[]}}}

and here is my code to get the values from a child:

boost::property_tree::ptree pt;
boost::property_tree::read_json(ss, pt);

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

    std::cout << "\njsonrpc: " << pt.get<std::string>("jsonrpc") << std::endl;
    std::cout << "\nmethod: " << pt.get<std::string>("method") << std::endl;
    std::cout << "\nparams: " << pt.get<std::string>("params") << std::endl;
    std::cout << "\nparams.channel: " << pt.get<std::string>("params.channel") << std::endl;
    std::cout << "\nparams.data: " << pt.get<std::string>("params.data") << std::endl;
    std::cout << "\nparams.data.timestamp: " << pt.get<std::string>("params.data.timestamp") << std::endl;
    std::cout << "\nparams.data.instrument_name: " << pt.get<std::string>("params.data.instrument_name") << std::endl;

but when I tried to parse the array values like ("params.data.bids") it return nothing

I need help in parsing an array

>Solution :

You should use a JSON Library:

Live On Compiler Explorer

#include <boost/json.hpp>
#include <boost/json/src.hpp> // header-only for Compiler Explorer
#include <iostream>
namespace json = boost::json;

int main() {
    auto req = json::parse(R"({
            "jsonrpc": "2.0",
            "method": "subscription",
            "params": {
                "channel": "book.BTC-PERPETUAL.raw",
                "data": {
                    "type": "change",
                    "timestamp": 1635513739435,
                    "prev_change_id": 6807100702,
                    "instrument_name": "BTC-PERPETUAL",
                    "change_id": 6807100703,
                    "bids": [
                        ["new", 60772.0, 50.0], "demo"],
                    "asks": []
                }
            }
        })") .as_object();

    auto& params = req["params"].as_object();
    auto& data   = params["data"].as_object();
    std::cout << "jsonrpc:                     " << req["jsonrpc"].as_string()    << "\n";
    std::cout << "methdo:                      " << req["method"].as_string()     << "\n";
    std::cout << "params.channel:              " << params["channel"].as_string() << "\n";
    std::cout << "params.data:                 " << params["data"]                << "\n";
    std::cout << "params.data.timestamp:       " << data["timestamp"]             << "\n";
    std::cout << "params.data.instrument_name: " << data["instrument_name"]       << "\n";

}

Prints

jsonrpc:                     "2.0"
methdo:                      "subscription"
params.channel:              "book.BTC-PERPETUAL.raw"
params.data:                 {"type":"change","timestamp":1635513739435,"prev_change_id":6807100702,"instrument_name":"BTC-PERPETUAL","change_id":6807100703,"bids":[["new",6.0772E4,5E1],"demo"],"asks":[]}
params.data.timestamp:       1635513739435
params.data.instrument_name: "BTC-PERPETUAL"
bid: ["new",6.0772E4,5E1]
bid: "demo"

Adding the asks/bids:

for (auto& bid : data["bids"].as_array()) {
    std::cout << "bid: " << bid << "\n";
}
for (auto& ask : data["asks"].as_array()) {
    std::cout << "ask: " << ask << "\n";
}

Prints

bid: ["new",6.0772E4,5E1]
bid: "demo"

Alternative / Bonus

You can also use value_to conversion to your own types:

struct request {
    std::string jsonrpc, method;
    struct params_t {
        std::string channel;
        struct data_t {
            std::string type;
            size_t timestamp, prev_change_id, change_id;
            std::string instrument_name;
            std::vector<json::value> bids, asks;
        } data;
    } params;
};

See it Live

Or flattened:

struct request {
    using values = std::vector<json::value>;
    std::string jsonrpc, method, channel, type, instrument_name;
    size_t      timestamp, prev_change_id, change_id;
    values      bids, asks;

    friend request tag_invoke(json::value_to_tag<request>, json::value const& v)
    {
        auto& params = v.at("params");
        auto& data   = params.at("data");
        return request{
            value_to<std::string>(v.at("jsonrpc")),
            value_to<std::string>(v.at("method")),
            value_to<std::string>(params.at("channel")),
            value_to<std::string>(data.at("type")),
            value_to<std::string>(data.at("instrument_name")),
            value_to<size_t>(data.at("timestamp")),
            value_to<size_t>(data.at("prev_change_id")),
            value_to<size_t>(data.at("change_id")),
            value_to<values>(data.at("bids")),
            value_to<values>(data.at("asks")),
        };
    }
};

See it Live As Well

#include <boost/json.hpp>
#include <boost/json/src.hpp> // header-only for Compiler Explorer
#include <iostream>
namespace json = boost::json;

struct request {
    using values = std::vector<json::value>;
    std::string jsonrpc, method, channel, type, instrument_name;
    size_t      timestamp, prev_change_id, change_id;
    values      bids, asks;

    friend request tag_invoke(json::value_to_tag<request>, json::value const& v)
    {
        auto& params = v.at("params");
        auto& data   = params.at("data");
        return request{
            value_to<std::string>(v.at("jsonrpc")),
            value_to<std::string>(v.at("method")),
            value_to<std::string>(params.at("channel")),
            value_to<std::string>(data.at("type")),
            value_to<std::string>(data.at("instrument_name")),
            value_to<size_t>(data.at("timestamp")),
            value_to<size_t>(data.at("prev_change_id")),
            value_to<size_t>(data.at("change_id")),
            value_to<values>(data.at("bids")),
            value_to<values>(data.at("asks")),
        };
    }
};

int main() {
    auto req = value_to<request>(json::parse(R"({
            "jsonrpc": "2.0",
            "method": "subscription",
            "params": {
                "channel": "book.BTC-PERPETUAL.raw",
                "data": {
                    "type": "change",
                    "timestamp": 1635513739435,
                    "prev_change_id": 6807100702,
                    "instrument_name": "BTC-PERPETUAL",
                    "change_id": 6807100703,
                    "bids": [
                        ["new", 60772.0, 50.0], "demo"],
                    "asks": []
                }
            }
        })"));

    std::cout << "jsonrpc:              " << req.jsonrpc << "\n";
    std::cout << "methdo:               " << req.method << "\n";
    std::cout << "params.channel:       " << req.channel << "\n";
    std::cout << "data.timestamp:       " << req.timestamp << "\n";
    std::cout << "data.instrument_name: " << req.instrument_name << "\n";

    for (auto& bid : req.bids) std::cout << "bid: " << bid << "\n";
    for (auto& ask : req.asks) std::cout << "ask: " << ask << "\n";
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading