Search code examples
c++jsonboost

How to parse below JSON with nested array in C++ and retrieve the result


I have a JSON like below which need to be parsed in C++ using read_json.

[
  {
    "key": "123",
    "revoked": false,
    "metadata": [
      {
        "visible": true,
        "key": "abc",
        "value": "0"
      },
      {
        "visible": true,
        "key": "cdf",
        "value": "0"      
      }     
    ],
    "meterAttributes": []
  }
]

In the above JSON, metadata and its key/value to be retrieved.

boost::property_tree::read_json(jsonString, pt);
for (auto& outerArray : pt)
    {
        for (auto& arrayProperty : outerArray.second)
        {
            if (arrayProperty.first == ws2s(metadata))
            {

The above code doesn't brought up the result as expected.


Solution

  • I'd suggest Boost JSON:

    #include <boost/json.hpp>
    #include <fmt/ranges.h>
    #include <iostream>
    namespace json = boost::json;
    
    int main() {
        std::map<std::string, std::string> kv;
    
        auto doc = json::parse(sample);
        for (auto& toplevel : doc.as_array()) {
            for (auto& md : toplevel.at("metadata").as_array()) {
                kv.emplace(md.at("key").as_string(), md.at("value").as_string());
            }
        }
    
        fmt::print("Parsed: {}\n", kv);
    }
    

    Printing: Live On Compiler Explorer

    Parsed: {("abc", "0"), ("cdf", "0")}
    

    Alternative

    If you insist on using Boost PropertyTree (e.g. because your data represents a property tree): Live On Compiler Explorer

    #include <boost/property_tree/json_parser.hpp>
    #include <fmt/ranges.h>
    #include <map>
    
    int main() {
        std::map<std::string, std::string> kv;
    
        boost::property_tree::ptree doc;
        std::istringstream          is(sample);
        read_json(is, doc);
    
        for (auto& [_, toplevel] : doc) {
            for (auto& [_, md] : toplevel.get_child("metadata")) {
                kv.emplace(md.get("key", ""), md.get("value", ""));
            }
        }
    
        fmt::print("Parsed: {}\n", kv);
    }
    

    Printing the same.