9

This should be simple (I'm just learning boost so I'm missing something)

I have read in some simple JSON using json_read and now have a ptree. All the examples on the web show using ptree.get("entry_name") to obtain an entry. All I want to do is something like:

 ptree pt;
 read_json(ss,pt);

 BOOST_FOREACH(ptree::value_type &v, pt)
 {
   std::cout << v.{entry_name} << v.{value}
 }

i.e. loop through the ptree and write out each name (i.e. what you put into pt.get()) and it's corresponding value.

Sorry if this is simple

Ross

Ross W
  • 1,300
  • 3
  • 14
  • 24

5 Answers5

18

I was searching the same thing, and couldn't find the answer anywhere. It turned out to be pretty simple indeed:

ptree pt;
/* load/fill pt */
for(iterator iter = pt.begin(); iter != pt.end(); iter++)
{
  std::cout << iter->first << "," << iter->second.data() << std::endl;
}

iter->first is the entry name, and iter->second.data() is the entry value of the first level. (You can then re-iterate with iter->second.begin()/end() for deeper levels.)

Further, if one such node in this iteration is not a terminal node and is itself a ptree, you can get that as ptree from this iterator itself : ptree subPt = iter->second.get_child("nodeName");

mr_georg
  • 3,635
  • 5
  • 35
  • 52
  • its an old post and too late to comment, but what if iter->second.data() is an array , this code would not work , is nt it ? – LearningCpp May 04 '17 at 08:05
  • 1
    Right, but if you read the text below the code, it is explained how to deal with non-terminals. – mr_georg May 20 '17 at 16:02
  • I can't get the text below the code to work for deeper levels of the ptree. I'm missing something or not understanding it correctly. – Dan Jan 22 '20 at 11:41
  • @Dan: can you elaborate, what is not working? What have you tried? If need be, you can start a new question. – mr_georg Jan 23 '20 at 14:22
  • Doesn't matter at this point. My problem is in essence just one of loading. I was just trying to learn a little about the boost::ptree to see if it would work out for my needs. AFIK it can't. I need to be able to do an XSL on large, complex XML file to dump it into a database with bulkinsert. I've tried several libraries and can't seem to get them running. If you've got any non-VS suggestions for loading and XSL transforming an XML, I'm all ears. – Dan Jan 23 '20 at 14:29
  • Maybe Xerces (http://xerces.apache.org). I used it years ago, and it is pretty mature. – mr_georg Jan 23 '20 at 14:38
2

I'm having troubles with ptree as well, but perhaps this can help: Check out boost's ptree quick tutorial

v.{entry_name}
would be
v.first

and

v.{value}
v.second.data()

Would that work?

Sam
  • 117
  • 11
1

Here's a great example of how to iterate a ptree using BOOST_FOREACH http://akrzemi1.wordpress.com/2011/07/13/parsing-xml-with-boost/

for direct access using the normal "get" functions look at the example from boost: http://www.boost.org/doc/libs/1_51_0/doc/html/boost_propertytree/tutorial.html

the documentation page is located here: http://www.boost.org/doc/libs/1_51_0/doc/html/boost/property_tree/basic_ptree.html I know its not very well documented but it is helpful.

Alex
  • 619
  • 1
  • 8
  • 25
1

Old thread, but here's a C++11 version of mr_georg's answer with range-based for loops:

ptree pt;
/* load/fill pt */
for(auto pair : pt)
{
  std::cout << pair.first << "," << pair.second.data() << std::endl;
}

For this json:

{
    "key1":"value1",
    "key2":"value2"
}

It outputs:

key1,value1
key2,value2
Stewart
  • 4,356
  • 2
  • 27
  • 59
0

This example iterates over a simple JSON object and puts its values into a vector.

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

#include <iostream>
#include <string>
#include <vector>
#include <sstream>

int main (void)
{   
    try
    {        
        std::stringstream ss;
        std::string json_obj_str = "{ \"unit_1\": 1, \"unit_2\": 2, \"unit_3\": 3 }";
        std::vector <float> fvec;

        ss << json_obj_str; // put string into stringstream

        boost::property_tree::ptree pt;
        boost::property_tree::read_json(ss, pt);    // put stringstream into property tree

        // iterate over JSON properties
        for (boost::property_tree::ptree::iterator iter = pt.begin(); iter != pt.end(); iter++)
        {
            std::cout << iter->first << ": " << iter->second.data() << std::endl;
            fvec.push_back(boost::lexical_cast<float>(iter->second.data()));
        }

        for (size_t i = 0; i < fvec.size(); i++)
        {
            std::cout << "fvec.at(" << i << ") = " << fvec.at(i) << std::endl;
        }
    }
    catch (const boost::property_tree::ptree_error &e)
    {
        std::cerr << "property_tree error = " << e.what() << std::endl;
        return -2;
    }       
    catch (std::exception const& e)
    {
        std::cerr << "exception = " << e.what() << std::endl;
        return -1;
    }

    return 0;
}
xinthose
  • 3,213
  • 3
  • 40
  • 59