Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse JSON array as std::string with Boost ptree

Tags:

c++

boost

I have this code that I need to parse/or get the JSON array as std::string to be used in the app.

std::string ss = "{ \"id\" : \"123\", \"number\" : \"456\", \"stuff\" : [{ \"name\" : \"test\" }] }";

ptree pt2;
std::istringstream is(ss);
read_json(is, pt2);
std::string id = pt2.get<std::string>("id");
std::string num= pt2.get<std::string>("number");
std::string stuff = pt2.get<std::string>("stuff"); 

What is needed is the "stuff" to be retrieved like this as std::string [{ "name" : "test" }]

However the code above stuff is just returning empty string. What could be wrong

like image 953
xkm Avatar asked Jul 10 '15 16:07

xkm


3 Answers

Arrays are represented as child nodes with many "" keys:

docs

  • JSON arrays are mapped to nodes. Each element is a child node with an empty name. If a node has both named and unnamed child nodes, it cannot be mapped to a JSON representation.

Live On Coliru

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

using boost::property_tree::ptree;

int main() {
    std::string ss = "{ \"id\" : \"123\", \"number\" : \"456\", \"stuff\" : [{ \"name\" : \"test\" }, { \"name\" : \"some\" }, { \"name\" : \"stuffs\" }] }";

    ptree pt;
    std::istringstream is(ss);
    read_json(is, pt);

    std::cout << "id:     " << pt.get<std::string>("id") << "\n";
    std::cout << "number: " << pt.get<std::string>("number") << "\n";
    for (auto& e : pt.get_child("stuff")) {
        std::cout << "stuff name: " << e.second.get<std::string>("name") << "\n";
    }
}

Prints

id:     123
number: 456
stuff name: test
stuff name: some
stuff name: stuffs
like image 136
sehe Avatar answered Oct 19 '22 02:10

sehe


Since "stuff" is an array, you can iterate over the elements of it, which are dictionaries. And then you can iterate over the elements of the dictionary, which are key-value pairs:

for (const auto& dict : pt2.get_child("stuff")) {
    for (const auto& kv : dict.second) {
        std::cout << "key = " << kv.first << std::endl;
        std::cout << "val = " << kv.second.get_value<std::string>() << std::endl;
    }
}
like image 25
Barry Avatar answered Oct 19 '22 03:10

Barry


continue with @sehe 's answer, related to the question asked by @xkm

Is it possible to get it like '[{ "name" : "some" }, { "name" : "stuffs" }]'

Yes, you can. Just treat it with an "unnamed" key which means the key with empty string.

f.g.

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

#include <iostream>

using boost::property_tree::ptree;

int main()
{
    std::stringstream ss;
    ss << R"([{"a": 5}, {"a": 9}])";

    ptree pt;
    read_json(ss, pt);
    for (auto& item : pt.get_child(""))
       std::cout << "value is " << item.second.get<int>("a") << std::endl;
}
like image 1
eshenhu Avatar answered Oct 19 '22 02:10

eshenhu