3

I know how to parse "normal" looking JSON data in C++. Usually, I do this, using boost::property_tree and read_json method. It may look like so:

BOOST_FOREAH(ptree::value_type &v, pt.get_child("rows"){
    vec.push_back(v.second.get<std::string>("key"));
}

and the code above corresponds to this JSON file:

{
    "rows":[{
         "key":"1"
     },{
         "key":"2"
     }]
}

However, the Neo4j result-set that I get, looks like:

{
    "columns":{...},
    "data":[[["object 1"]], [["object 2"]], [["object 3"]]]
}

I'm interested and want to parse "data" node. I tried to do it like so:

BOOST_FOREAH(ptree::value_type &v, pt.get_child("data"){
    vec.push_back(v.second.data());
}

but this does not work. I do not get an error, but my vector vec remains empty, or to be more precise it is populated with empty values. So, that when I iterate through this vec I see a number of elements, but they do not have any value. Whereas, I want to have values "object 1", "object 2", "object 3".

9
  • github.com/jeaye/jeayeson, json_spirit, to name just two libraries that will do this. Commented Aug 8, 2015 at 20:34
  • These libraries look promissing, but are you 100% sure, that they will parse my json file? Commented Aug 8, 2015 at 20:45
  • 1
    @Jacobian If library claims that it supports parsing of standard JSON then it will parse standard JSON otherwise it is buggy. Or your question is not clear. Commented Aug 8, 2015 at 21:00
  • 1
    The answer is literally in the ~20 lines of documentation specific to the JSON backend. It's also a very frequently asked question here so a quick search of boost-propertytree + array should give you helpful answers in seconds. I would like to conclude with my caveat that Boost doesn't come with a JSON or XML library. It does have a property tree library. People confusing the two are a very frequent occurrence and Stack Overflow is littered with the wreckage of that. Commented Aug 8, 2015 at 22:02
  • Boost comes with json_parser Commented Aug 8, 2015 at 22:06

2 Answers 2

2

The solution looks like this:

using boost::property::ptree;
ptree pt;
//... populate ptree pt with data from some source
BOOST_FOREACH(ptree::value_type &v, pt.get_child('data')){
    ptree subtree1 = v.second;
    BOOST_FOREACH(ptree::value_type &vs, subtree1){
        ptree subtree2 = vs.second;
        BOOST_FOREACH(ptree::value_type &vs2, subtree2){
            do_something(vs2.second.data());
        }
    }
}

This code makes it possible to parse such JSON structure:

{
 "data":[[["object 1"]], [["object 2"]], [["object 3"]]]
}

So, contrary to what some people are saying, actually, there is no need to use other third-party libraries. Use just boost and you are done.

Sign up to request clarification or add additional context in comments.

2 Comments

Though, I do not like this code. I wish there was some sort of simplification. Since, copy pasting BOOST_FOREACH looks rather technical.
Indeed. There's often no need for third party libraries. Although you're just lucky this covers your needs. Good luck if ever you need to format a proper JSON number. This is why is even worse to evangelise Boost Property Tree as a JSON library.
0

This is an example of how I do it. You have to know the JSON structure ahead of time.

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

boost::property_tree::ptree pt, sub_pt;
std::string json_str, key, sub_key;
std::stringstream ss;
int value = 0, bus_num = 0;

json_str = "{\"arduino_1\": {\"bus_1\": 17425,\"bus_2\": 1025,\"bus_3\": 0,\"bus_4\": 0,\"bus_5\": 0,\"bus_6\": 0,\"bus_7\": 0,\"bus_8\": 0}}";


ss << json_str; // put string into stringstream
boost::property_tree::read_json(ss, pt);    // put stringstream into property tree
for (boost::property_tree::ptree::iterator iter = pt.begin(); iter != pt.end(); iter++)
{
    // get data
    key = boost::lexical_cast <std::string>(iter->first.data());
    sub_pt = iter->second;

    // iterate over subtree
    for (boost::property_tree::ptree::iterator sub_iter = sub_pt.begin(); sub_iter != sub_pt.end(); sub_iter++)
    {
        // get data
        sub_key = boost::lexical_cast <std::string>(sub_iter->first.data());
        value = boost::lexical_cast <int>(sub_iter->second.data());
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.