Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing JSON with boost property tree

I'm building an application that gets movie information from themoviedb.com. The information is provided in a JSON file. I'm trying to store the information using boost property tree. But There is a little problem.

I illustrate the problem by the following code:

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

using namespace std;
using boost::property_tree::ptree;

class single_t{
    int             sID;
    string          sName;
public:
    void            setID(int ID){sID=ID;}
    int             getID(){return sID;}
    void            setName(string Name){sName=Name;}
    string          getName(){return sName;}
};

typedef vector<single_t*> multiple_t;

class foo{
    string          fTitle;
    multiple_t      fItems;
public:
    string          getTitle(){return fTitle;}
    void            setTitle(string Title){fTitle=Title;}
    multiple_t      getItems(){return fItems;}
    void            setItems(multiple_t Items){fItems = Items;}
    void            setItems(single_t Item){fItems.push_back(&Item);}
};

int main () {
    try{
        string response = "{\"title\":\"Foo\",\"items\":[{\"id\":123,\"name\":\"test1\"},{\"id\":456,\"name\":\"test2\"}]}";

        ptree pt;
        stringstream ss; ss << response;
        read_json(ss, pt);
        foo results;
        results.setTitle(pt.get<string>("title"));
        BOOST_FOREACH(ptree::value_type &v,pt.get_child("items")){
            single_t result;
            result.setID(v.second.get<int>("id"));
            result.setName(v.second.get<string>("name"));
            results.setItems(result);
        }
        cout << "Tilte: " << results.getTitle() << endl;
        cout << "Items:" << endl;
        for (int i=0; i!=results.getItems().size(); i++) {
            cout << "\tID: " << results.getItems()[i]->getID()<< endl;
            cout << "\tName: " << results.getItems()[i]->getName()<< endl;
        }
    }
    catch (exception& e)
    {
        cout << "Exception: " << e.what();
    }

}

But when I run this I get the following output:

Tilte: Foo
Items:
  ID: 456
  Name: test2
  ID: 456
  Name: test2

Does anyone know what I'm doing wrong? I guess it is in the BOOST_FOREACH code.

PS: Using Xcode 4.5.2 with LLVM GCC 4.2 Compiler.

like image 757
Glenn Vonk Avatar asked Dec 20 '12 12:12

Glenn Vonk


People also ask

How do you use the boost property tree?

By default, Boost. PropertyTree uses a dot as the separator for keys. If you need to use another character, such as the backslash, as the separator, you don't pass the key as a string to put() . Instead you wrap it in an object of type boost::property_tree::ptree::path_type .

What is boost property tree?

The Property Tree library provides a data structure that stores an arbitrarily deeply nested tree of values, indexed at each level by some key. Each node of the tree stores its own value, plus an ordered list of its subnodes and their keys.


Video Answer


1 Answers

Problem is not with property_tree, problem is, that you try store pointer to local variable in vector. You can save by value, or use some smart pointer (for example boost::shared_ptr).

Problem:

void            setItems(single_t Item){fItems.push_back(&Item);}

After exit from this function, local variable Item will be destroyed, so you have dangling pointer.

like image 116
ForEveR Avatar answered Sep 18 '22 12:09

ForEveR