With my tree looking like this:
{
"Library":
{
"L_ID": "1",
"Book":
{
"B_ID": "1",
"Title": "Moby Dick"
},
"Book":
{
"B_ID": "2",
"Title": "Jurassic Park"
}
},
"Library":
{
"L_ID": "2",
"Book":
{
"B_ID": "1",
"Title": "Velocity"
},
"Book":
{
"B_ID": "2",
"Title": "Creeper"
}
}
}
What i am looking to do is iterate through the libraries. When i find the L_ID that i am looking for, iterate through the books until i find the B_ID i'm looking for. At that point, i'd like to access all the leaves in that section. I.e. looking for library 2, book 1, title Note: There's likely a better way than this.
boost::property_tree::ptree libraries = config_.get_child("Library");
for (const auto &lib : libraries)
{
if (lib.second.get<uint16_6>("L_ID") == 2)
{
//at this point, i know i'm the correct library...
boost::property_tree::ptree books = lib.get_child("Book");
for (const auto &book : books)
{
if (book.second.get<uint16_t>("B_ID") == 1)
{
std::string mybook = book.second.get<std::string>("Title");
}
}
}
I fail out as soon as i try looking into my first sub tree. What's going wrong here??
@Sehe fixed your JSON to be syntactically correct, but I think it would make sense to go a bit further than that. Given the data you're representing, it would make a great deal more sense to have an array of libraries, each of which contains an array of books, giving data something like this:
Then, if at all possible, I'd choose a library that's actually suited to the job at hand. Boost property tree isn't really intended as a general-purpose JSON library. You can push it into that role if you really insist, but at least for what you've outlined in the question, it puts you through quite a bit of extra work to get what you want.
Personally, I'd probably use nlohmann's JSON library instead. Using it, we can proceed a little more directly to a solution. Basically, once it's parsed a JSON file, we can treat the result a great deal like we would normal collections from the standard library--we can use all the normal algorithms, range-based
for
loops, and so on. So, we can load a JSON file something like:Then we can look through the libraries for a particular ID number with code something like this:
Looking for a particular book is nearly identical:
From there, printing out the title looks something like:
std::cout << book["Title"];
Putting those together, we could end up with code something like this:
If you really want to convert each JSON object into a C++ object, you can do that fairly easily as well. It would look something like this:
So there are two points here: you must name the function
from_json
, and it must be defined in the same namespace as the struct/class it's associated with. With this bit of scaffolding in place, we can convert from JSON to struct with a simple assignment, something like this:I'd consider it highly questionable whether that's really useful in this particular case though.
For starters, the "JSON" is wildly flawed. At least fix the missing quotes and commas:
Next up, you seem to be confused.
get_child("Library")
gets the first child by that name, not a node containing child nodes called "Library" (that would be the root node, by the way).May I suggest adding some abstraction, and perhaps some facilities to query by some names/properties:
As you can see, we assume a
Config
type that can find a library:What is
libraries()
? We'll delve into it deeper, but lets just look at it for a second:That magic should be read as "give me all nodes that are named Library, which have a L_ID property but wrap them in a Library object". Skipping on the detail for now, lets look at the
Library
object, which apparently knows aboutbooks()
:We see the same pattern in
books()
andbook(id)
to find a specific item.The Magic
The magic uses Boost Range adaptors and lurks in
PtreeTools
:That's deceptively simple, right. That's because we're standing on the shoulders of Boost Range:
Next, we only define the predicates that know how to filter for a specific ptree node:
And one transformation to project to our wrapper objects:
Full Live Demo
Live On Coliru
Prints: