5

I have this code that I need to parse/or get the JSON array as std::string to be used in the app.

std::string ss = "{ \"id\" : \"123\", \"number\" : \"456\", \"stuff\" : [{ \"name\" : \"test\" }] }";

ptree pt2;
std::istringstream is(ss);
read_json(is, pt2);
std::string id = pt2.get<std::string>("id");
std::string num= pt2.get<std::string>("number");
std::string stuff = pt2.get<std::string>("stuff"); 

What is needed is the "stuff" to be retrieved like this as std::string [{ "name" : "test" }]

However the code above stuff is just returning empty string. What could be wrong

1
  • [OT]: Good place to use raw string here: ss = R"({ "id":"123", "number":"456", "stuff":[{"name":"test"}] })". Commented Jul 10, 2015 at 16:40

3 Answers 3

7

Arrays are represented as child nodes with many "" keys:

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.

Live On Coliru

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

using boost::property_tree::ptree;

int main() {
    std::string ss = "{ \"id\" : \"123\", \"number\" : \"456\", \"stuff\" : [{ \"name\" : \"test\" }, { \"name\" : \"some\" }, { \"name\" : \"stuffs\" }] }";

    ptree pt;
    std::istringstream is(ss);
    read_json(is, pt);

    std::cout << "id:     " << pt.get<std::string>("id") << "\n";
    std::cout << "number: " << pt.get<std::string>("number") << "\n";
    for (auto& e : pt.get_child("stuff")) {
        std::cout << "stuff name: " << e.second.get<std::string>("name") << "\n";
    }
}

Prints

id:     123
number: 456
stuff name: test
stuff name: some
stuff name: stuffs
Sign up to request clarification or add additional context in comments.

3 Comments

Is it possible to get it like '[{ "name" : "some" }, { "name" : "stuffs" }]' <-- this
@xkm Yes. write_json(some_stream, pt.get_child("stuff"));. Make some_stream a std::ostringstream so you can use some_stream.str() to get the text
@sehe I would like to do it without the auto& e for loop. Can we not access the elements as pt.get_child("stuff").name[0] and it gives value test.
1

Since "stuff" is an array, you can iterate over the elements of it, which are dictionaries. And then you can iterate over the elements of the dictionary, which are key-value pairs:

for (const auto& dict : pt2.get_child("stuff")) {
    for (const auto& kv : dict.second) {
        std::cout << "key = " << kv.first << std::endl;
        std::cout << "val = " << kv.second.get_value<std::string>() << std::endl;
    }
}

Comments

1

continue with @sehe 's answer, related to the question asked by @xkm

Is it possible to get it like '[{ "name" : "some" }, { "name" : "stuffs" }]'

Yes, you can. Just treat it with an "unnamed" key which means the key with empty string.

f.g.

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

#include <iostream>

using boost::property_tree::ptree;

int main()
{
    std::stringstream ss;
    ss << R"([{"a": 5}, {"a": 9}])";

    ptree pt;
    read_json(ss, pt);
    for (auto& item : pt.get_child(""))
       std::cout << "value is " << item.second.get<int>("a") << std::endl;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.