I am using boost-property-tree in a C++ application, where I am trying to read a JSON file users.json
and store the data into a vector of object (std::vector<User> users;
).
The JSON file looks this this:
{
"OperatingSystem":"Windows 10",
"users" :
[
{
"firstName":"John",
"lastName":"Black"
},
{
"firstName":"Kate",
"lastName":"Red"
},
{
"firstName":"Robin",
"lastName":"White"
}
]
}
I have succedded reading the OperatingSystem
property with the following line of code:
boost::property_tree::ptree treeRoot;
boost::property_tree::read_json("users.json", treeRoot);
std::string operatingSystem = treeRoot.get<std::string>("OperatingSystem");
std::cout << "OS : " << operatingSystem << std::endl;
and that works fine.
In order to store the users, I have created a User class. You can see the header file User.hpp
below:
#ifndef USER_H
#define USER_H
#include <iostream>
#include <string>
class User
{
private:
// Properties
std::string firstName;
std::string lastName;
public:
// Constructors
User();
User(std::string firstName, std::string lastName);
// Getters
std::string getFirstName();
std::string getLastName();
// Setters
void getFirstName(std::string firstName);
void getLastName(std::string lastName);
};
#endif // USER_H
and the User.cpp
file here:
#include "User.hpp"
#include <iostream>
#include <string>
// Constructors
User::User()
{
this->firstName = "";
this->lastName = "";
}
User::User(std::string firstName, std::string lastName)
{
this->firstName = firstName;
this->lastName = lastName;
}
// Getters
std::string User::getFirstName()
{
return firstName;
}
std::string User::getLastName()
{
return lastName;
}
// Setters
void User::getFirstName(std::string firstName)
{
this->firstName = firstName;
}
void User::getLastName(std::string lastName)
{
this->lastName = lastName;
}
In my main.cpp
I am trying to load the users into a vector as such:
#include <iostream>
#include <string>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include "User.hpp"
int main(int argc, char **argv)
{
boost::property_tree::ptree treeRoot;
boost::property_tree::read_json("users.json", treeRoot);
std::vector<User> users;
users = treeRoot.get<std::vector<User>>("users");
return 0;
}
but it does not work.
In case someone knows how to read an array of objects from a JSON file via boost::property_tree::ptree
, please let me know.
In property_tree
arrays JSON are mapped into nodes (called just ptree
).
What is node/ptree ?
node/ptree {
data // has data
list < pair<key,node> > children // has children
}
In your input object you have property users with value as the array with 3 elements. These elements are mapped into three nodes with empty string as key.
So we have:
"users" node:
children {"",nodeA}, {"",nodeB}, {"",nodeC}
nodeA,B,C
represents elements of arrays. Each element of array is object with 2 properties. Objects like arrays are also mapped into nodes.
So nodeA
looks like:
nodeA:
children {"firstName",nodeD},{"lastName",nodeE} \\ as children we have 2 properties of object
and finally, nodeD
is
nodeD:
data = John
children emptyList
To get users property call get_child()
.
To iterate over all children use begin\end
methods on ptree
returned by get
. begin\end
returns iterator to pair with first
as key, and second
as nested ptree instance.
The below code iterates over elements in array:
boost::property_tree::ptree pt;
boost::property_tree::read_json("in.json",pt);
auto it = pt.get_child("users");
for (auto it2 = it.begin(); it2 != it.end(); ++it2)
{
for (auto it3 = it2->second.begin(); it3 != it2->second.end(); ++it3)
{
std::cout << it3->first; // [1]
std::cout << " : " << it3->second.data() << std::endl;
}
// [2]
std::cout << std::endl;
}
and prints:
firstName : John
lastName : Black
firstName : Kate
lastName : Red
firstName : Robin
lastName : White
in [1] line you should store firstName
/lastName
and in [2] line you could create new User
instance and push into vector.