Monday, February 16, 2015

Using boost.property_tree.ptree to store JSON data

A Property Tree in Boost is a data structure that can store information in a tree-like format. Each node having a key and a value. It can be used to store XML, INI, INFO and JSON formats. Maybe also other, but these are the most popular and they are supported by boost, with ready-to-use parsers.
The limitation for JSON handling, is that property trees do not support simple arrays, since all nodes are of key-value type.

Let's see first an example of a JSON without arrays.
Populating a boost::property_tree::ptree data structure can be done with the provided boost::property_tree::read_json functions:
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

try{
    std::string json_file("json file path");
    boost::property_tree::ptree pt;
    boost::property_tree::json_parser::read_json(json_file, pt);
}
catch(boost::property_tree::json_parser_error ex){
    std::cout << ex.what() << std::endl;
}
For the following JSON:
{
  "name": "Joe",
  "Age": "20",
  "size" : {
    "Height": 180,
    "Weight": 80
  }
}
the generated tree is:

 * name="Joe"  
 * Age="20"  
 * size  
  * Height="180"  
  * Weight="80"  

The contents above were printed in the console and represent a tree. Link to source code will be provided at the end of the article.

Now, for a JSON that contains arrays:
{
  "sitename": "joys of programming",
  "categories": [
    "c",
    [
      "c++",
      "c"
    ],
    "java",
    "PHP",
    [
      "Bash",
      "Batch",
      [
        "Lua",
        "Lua_ex"
      ]
    ]
  ],
  "author-details": {
    "admin": false,
    "name": "Joys of Programming",
    "Number of Posts": 10
  }
}
the generated tree is:
 * sitename="joys of programming"
* categories
  * 
  * 
    * 
    * 
  * 
  * 
  * 
    * 
    * 
    * 
      * 
      * 
* author-details
  * admin="false"
  * name="Joys of Programming"
  * Number of Posts="10"

As you can see the array elements are not populated by the default boost json parser.

As a solution to this issue, I wrote a parser and manually added the nodes in the tree, adding a default key (the index) for the array value so that the ptree can hold the data. With this solution, the generated tree for the last JSON will look like this:
 * sitename="joys of programming"
* categories
  * 0="c"
  * 1
    * 0="c++"
    * 1="c"
  * 2="java"
  * 3="PHP"
  * 4
    * 0="Bash"
    * 1="Batch"
    * 2
      * 0="Lua"
      * 1="Lua_ex"
* author-details
  * admin="false"
  * name="Joys of Programming"
  * Number of Posts="10"
Parsing the ptree should be trivial, using BOOST_FOREACH and ignoring the index keys. Although the index keys might be useful for knowing the index of the element when iterating.

The source code for the solution can be found at this location:  https://github.com/alexandruc/json2ptree.

No comments:

Post a Comment