28

I have some JSON with a handful of integer array variables, like so:

{"a": [8, 6, 2], "b": [2, 2, 1]}

I would like to use boost property_tree, for instance:

std::stringstream ss;
boost::property_tree::ptree pt;

ss << "{\"a\": [8, 6, 2], \"b\": [2, 2, 1]}";

boost::property_tree::read_json(ss, pt);
std::vector<int> a = pt.get<std::vector<int> >("a");

This doesn't work, nor does any variation on an int pointer that I've tried. How may I read an array from a property tree?

lethal-guitar
  • 4,101
  • 1
  • 16
  • 38
Larry
  • 319
  • 1
  • 4
  • 10
  • possible duplicate of [Parsing JSON with boost property tree](http://stackoverflow.com/questions/13972252/parsing-json-with-boost-property-tree) – lethal-guitar May 05 '14 at 21:51
  • 1
    The answer to that question does not cover the specific case of arrays, so I respectfully disagree. Incidentally, the answer to this question is forthcoming. – Larry May 05 '14 at 22:10
  • But the question itself has code on dealing with arrays, and there's an array in the example data. He extracts the elements using a loop. – lethal-guitar May 05 '14 at 22:16
  • oh, I see what you mean. The question as asked contains the answer to my question. I feel that this isn't obvious, though. Intuitively, it would make sense to me that arrays of primitives would be parsed directly. A concise answer to my question would read something like "each element in a primitive type array is a special case of a child node" – Larry May 05 '14 at 22:25

2 Answers2

27

JSON support, is spotty with boost property tree.

The property tree dataset is not typed, and does not support arrays as such. Thus, the following JSON / property tree mapping is used:

  • JSON objects are mapped to nodes. Each property is a child node.
  • 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.
  • JSON values are mapped to nodes containing the value. However, all type information is lost; numbers, as well as the literals "null", "true" and "false" are simply mapped to their string form.
  • Property tree nodes containing both child nodes and data cannot be mapped.

(from the documentation)

You can iterate the array with a helper function.

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

using boost::property_tree::ptree;

template <typename T>
std::vector<T> as_vector(ptree const& pt, ptree::key_type const& key)
{
    std::vector<T> r;
    for (auto& item : pt.get_child(key))
        r.push_back(item.second.get_value<T>());
    return r;
}

int main()
{
    std::stringstream ss("{\"a\": [8, 6, 2], \"b\": [2, 2, 1]}");

    ptree pt;
    read_json(ss, pt);

    for (auto i : as_vector<int>(pt, "a")) std::cout << i << ' ';
    std::cout << '\n';
    for (auto i : as_vector<int>(pt, "b")) std::cout << i << ' ';
}

See it Live On Coliru. Output:

8 6 2 
2 2 1
sehe
  • 328,274
  • 43
  • 416
  • 565
14

Read your a list as follows:

#include <boost/foreach.hpp>
BOOST_FOREACH(boost::property_tree::ptree::value_type &v, pt.get_child("a.")) {
    cout << v.second.data() << endl;
}
Derek Illchuk
  • 5,472
  • 1
  • 26
  • 29