30

I have a file like this:

[data.json]

{
    "electron": {
        "pos": [0,0,0],
        "vel": [0,0,0]
    },

    "proton": {
        "pos": [1,0,0],
        "vel": [0,0.1,0]
    },

     "proton": {
        "pos": [-1,0,0],
        "vel": [0,-0.1,-0.1]
    }
}

How do I create a vector of particles from parsing this file. As I understand it I need to read the file using boost and read the strings (lines) into a vector, and then parse the contents of the vector.

The class particle is something like this:

class Particle
{

    private:
    particle_type mtype; // particle_type is an enum
    vector<double> mPos;
    vector<double> mVel;
};

Other methods for get/set have been omitted in the class.

Basically I would like help creating a vector<Particle> with the correct position and velocity data and particle_type data parsed into it. Thanks in advance.

Code in main:

int main(){

    boost::property_tree::ptree pt;
    boost::property_tree::read_json("data.json", pt);
}
6

3 Answers 3

29

I modified your JSON a bit. Slightly untested code.

{
    "particles": [
        {
            "electron": {
                "pos": [
                    0,
                    0,
                    0
                ],
                "vel": [
                    0,
                    0,
                    0
                ]
            },
            "proton": {
                "pos": [
                    -1,
                    0,
                    0
                ],
                "vel": [
                    0,
                    -0.1,
                    -0.1
                ]
            }
        }
    ]
}

...

#ifdef _MSC_VER
#include <boost/config/compiler/visualc.hpp>
#endif
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/foreach.hpp>
#include <cassert>
#include <exception>
#include <iostream>
#include <sstream>
#include <string>

int main()
{
    try
    {
        std::stringstream ss;
        // send your JSON above to the parser below, but populate ss first


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

        BOOST_FOREACH(boost::property_tree::ptree::value_type &v, pt.get_child("particles.electron"))
        {
            assert(v.first.empty()); // array elements have no names
            std::cout << v.second.data() << std::endl;
            // etc
        }
        return EXIT_SUCCESS;
    }
    catch (std::exception const& e)
    {
        std::cerr << e.what() << std::endl;
    }
    return EXIT_FAILURE;
}

Modify as you see fit.

Print the entire tree to see what is being read. This helps in debugging.

void print(boost::property_tree::ptree const& pt)
{
    using boost::property_tree::ptree;
    ptree::const_iterator end = pt.end();
    for (ptree::const_iterator it = pt.begin(); it != end; ++it) {
        std::cout << it->first << ": " << it->second.get_value<std::string>() << std::endl;
        print(it->second);
    }
}
10
  • I did not find this helpful - No such node (particles.electron). For anyone who is not familiar, std::stringstream ss should be removed, and boost::property_tree::read_json(ss, pt); replaced with boost::property_tree::read_json(<YOUR PATH TO AND FILE NAME HERE>, pt); Commented Mar 4, 2013 at 21:58
  • @EdwardBird: read_json takes a stream, its in boost's documentation. You must not have populated it correctly.
    – user195488
    Commented Mar 4, 2013 at 22:21
  • what do you suggest. (See my edit in main) EDIT: There is nothing for me to add in main... What do you suggest? Commented Mar 4, 2013 at 22:22
  • When I print the tree everything looks fine. Commented Mar 4, 2013 at 22:24
  • 2
    This example was helpful, but is wrong, it really is worth getting examples to work before posting them IMHO. Commented Jan 6, 2014 at 16:58
9

You can iterate with the following code :

boost::property_tree::basic_ptree<std::string,std::string>::const_iterator iter = pt.begin(),iterEnd = pt.end();
for(;iter != iterEnd;++iter)
{
     iter->first; // Your key, at this level it will be "electron", "proton", "proton"
     iter->second; // The object at each step {"pos": [0,0,0], "vel": [0,0,0]}, etc.
}

Hope it helps

2
  • Iter has a first and a second... But what are they? Is there a third as well? Commented Mar 4, 2013 at 17:06
  • 1
    iter is a pair, so there is no third. v.first is an std::string holding the parent node and v.second is a boost::property_tree::ptree, which can be used to parse the fields of the object. You may have to recursively traverse the tree to get all the values depending on how deep your values are buried.
    – user195488
    Commented Mar 4, 2013 at 17:18
6

Just correcting issues with the answer above but I couldnt get the formating correct in the comments:

#ifdef _MSC_VER
#include <boost/config/compiler/visualc.hpp>
#endif
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/foreach.hpp>
#include <cassert>
#include <exception>
#include <iostream>
#include <sstream>
#include <string>

void print(boost::property_tree::ptree const& pt)
{
    using boost::property_tree::ptree;
    ptree::const_iterator end = pt.end();
    for (ptree::const_iterator it = pt.begin(); it != end; ++it) {
        std::cout << it->first << ": " << it->second.get_value<std::string>() << std::endl;
        print(it->second);
    }
}

int main()
{
    try
    {
        std::stringstream ss;
        // send your JSON above to the parser below, but populate ss first

        ss << "{ \"particles\": [ { \"electron\": { \"pos\": [ 0, 0, 0 ], \"vel\": [ 0, 0, 0 ] }, \"proton\": { \"pos\": [ -1, 0, 0 ], \"vel\": [ 0, -0.1, -0.1 ] } } ]}";


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

        BOOST_FOREACH(boost::property_tree::ptree::value_type &v, pt.get_child("particles"))
        {
            assert(v.first.empty()); // array elements have no names
            print(v.second);
        }
        return EXIT_SUCCESS;
    }
    catch (std::exception const& e)
    {
        std::cerr << e.what() << std::endl;
    }
    return EXIT_FAILURE;
}
3
  • still, the program is not running the error is "‘print’ was not declared in this scope " I tried to change it to printf but it did not work.
    – Aloy A Sen
    Commented Dec 5, 2017 at 14:00
  • print is defined below the main function using ptree types not print. Perhaps you forgot to copy the entire content above. I don't have a computer to retest with right now.
    – Jim
    Commented Dec 5, 2017 at 17:30
  • Perhaps print needs to be pasted above main
    – Jim
    Commented Dec 5, 2017 at 17:31

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.