Previously we looked at how to create a new JSON node tree programmatically that could be sent over the wire to consumer. Now we'll look at the consumer side and see how to parse the JSON string into our application.
First we'll look at the main function in our program that will take a JSON string as input, parse it using the library and pass the tree to a function that will extract useful data.
std::string json = "{\"RootA\":\"Value in parent node\",\"ChildNode\":{\"ChildA\":\"String Value\",\"ChildB\":42}}"; JSONNode n = libjson::parse(json); ParseJSON(n);
The first line is just a simple JSON string containing a child object. You'll likely get a string from a web service, message buss or even a file.
Line 2 is where the magic happens in the library. We just pass the string to libjson::parse and if all is well, we'll receive a node tree in return. NOTE that the parser is going to allocate memory on the stack, so do not try and delete it, let it go out of scope.
Line 3 is a function call that we define for iterating through the JSON tree. While mine isn't pretty, it gets the job done for simple JSON objects.
void ParseJSON(const JSONNode & n){ JSONNode::const_iterator i = n.begin(); while (i != n.end()){ // recursively call ourselves to dig deeper into the tree if (i -> type() == JSON_ARRAY || i -> type() == JSON_NODE){ ParseJSON(*i); } // get the node name and value as a string std::string node_name = i -> name(); // find out where to store the values if (node_name == "RootA"){ rootA = i -> as_string(); } else if (node_name == "ChildA"){ childA = i -> as_string(); } else if (node_name == "ChildB") childB = i -> as_int(); //increment the iterator ++i; } }
Next on line 7 we get a pointer to the first iterator of the node we're currently dealing with. The iterator lets us navigate through the child nodes, one by one.
Line 8 begins a while loop that will continue until we've reached the final iterator returned by json_end.
If the iterator is currenly pointing to a node of type JSON_ARRAY or JSON_NODE, that means we are at a branch that requires a new iterator for processing. Thus line 16 makes a recursive call to the function so that we can start processing on the child node. Without this call, we would get the name of the node but trying to get a value would return nothing.
On line 20 we call the name method that will return a string with the name of the node. If the node is not named or it's an array's value, the string will be empty, so check for that.
Lines 23 through 34 are a simple decision tree that attempt to match the name of the node to known values and if a match is made, we use one of the library functions to extract the value of the node. as_string naturally returns the value of the node as a string. This is probably the easiest to use in that it doesn't care if the value of the node is encased in quotation marks or not, it will always return a string. You can read any node as a string and then typecast to whatever need.
Line 38 increments our iterator to the next node.
So there you have a very simple little parser that will iterate through your tree and grab extract the data. Naturally you'll want to add error handling and tweak it for your own use.