The Unterminated String

Embedded Things and Software Stuff

Populating Boost Ptree JSON Arrays

Posted at — Jun 17, 2020

Boost Property Tree offers a simple interface for parsing and writing JSON.

It is not without its limitations however, one of which being that working with arrays isn’t particularly intuitive. This is at least partly due to the array elements being modelled as having empty keys. Per the docs:

JSON arrays are mapped to nodes. Each element is a child node with an empty name. If a node has both named and unnamed child nodes, it cannot be mapped to a JSON representation.

I use arrays infrequently enough that I tend to forget how to manipulate them. So I’ve put the following example together as a reference to myself.

The following is a decomposed source file with the example JSON shown after each modification.

Headers and Namespaces

#include <algorithm>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <iostream>

namespace bpt = boost::property_tree;

Build Array

Code

bpt::ptree build_array()
{
    bpt::ptree array_elem0;
    array_elem0.put("name", "Julius Zeleny");
    array_elem0.put("birthday", "1991-01-01");
    array_elem0.put("phone", "(111) 11111111");

    bpt::ptree array_elem1;
    array_elem1.put("name", "Owen Cohron");
    array_elem1.put("birthday", "1992-02-02");
    array_elem1.put("phone", "(222) 22222222");

    bpt::ptree array;
    array.push_back(
        bpt::ptree::value_type("", array_elem0));
    array.push_back(
        bpt::ptree::value_type("", array_elem1));

    bpt::ptree full;
    full.put_child("contacts.friends", array);

    return full;
}

Output

{
    "contacts": {
        "friends": [
            {
                "name": "Julius Zeleny",
                "birthday": "1991-01-01",
                "phone": "(111) 11111111"
            },
            {
                "name": "Owen Cohron",
                "birthday": "1992-02-02",
                "phone": "(222) 22222222"
            }
        ]
    }
}

Append to Array

Code

void append_to_array(bpt::ptree &tree)
{
    bpt::ptree array_elem2;
    array_elem2.put("name", "Margherita Horgan");
    array_elem2.put("birthday", "1993-03-03");
    array_elem2.put("phone", "(333) 33333333");

    bpt::ptree &array =
        tree.get_child("contacts.friends");

    array.push_back(
        bpt::ptree::value_type("", array_elem2));
}

Output

{
    "contacts": {
        "friends": [
            {
                "name": "Julius Zeleny",
                "birthday": "1991-01-01",
                "phone": "(111) 11111111"
            },
            {
                "name": "Owen Cohron",
                "birthday": "1992-02-02",
                "phone": "(222) 22222222"
            },
            {
                "name": "Margherita Horgan",
                "birthday": "1993-03-03",
                "phone": "(333) 33333333"
            }
        ]
    }
}

Delete from Array

Raw Loop

void delete_from_array_for(bpt::ptree &tree)
{
    bpt::ptree &array =
        tree.get_child("contacts.friends");

    for (bpt::ptree::iterator element = array.begin();
         element != array.end();
         element++)
    {
        if (element->second.get<std::string>("name") ==
            "Margherita Horgan")
        {
            array.erase(element);
            return;
        }
    }
}

STL Find

void delete_from_array_find(bpt::ptree &tree)
{
    bpt::ptree &array =
        tree.get_child("contacts.friends");

    bpt::ptree::iterator result = std::find_if(
        array.begin(),
        array.end(),
        [](bpt::ptree::value_type const &element) {
            return element.second.get<std::string>(
                       "name") == "Julius Zeleny";
        });

    if (result != array.end())
    {
        array.erase(result);
    }
}

Output

{
    "contacts": {
        "friends": [
            {
                "name": "Owen Cohron",
                "birthday": "1992-02-02",
                "phone": "(222) 22222222"
            }
        ]
    }
}

Rest of Code

void log_json(bpt::ptree const &tree)
{
    std::stringstream json;
    bpt::write_json(json, tree);
    std::cout << json.str();
}

int main()
{
    bpt::ptree tree = build_array();
    log_json(tree);

    append_to_array(tree);
    log_json(tree);

    delete_from_array_find(tree);
    delete_from_array_for(tree);
    log_json(tree);

    return 0;
}