1

I need to read a field in a JSON file which itself is a JSON. I need to read the JSON field in one go. Is there any way available? Sample JSON I am trying to read is provided below.

enter code here
   {
      "responses": [
       { 
          "id": "1",
          "status": 200,
          "headers": {
                 "OData-Version": "4.0",
                 "Content-Type":"application/json;odata.metadata=minimal;odata.streaming=true"
           },
          "body": {        
              "createdDateTime": "2021-04-22T09:24:59.394Z",
              "displayName": "Test1",        
              "visibility": "public",        
              "isMembershipLimitedToOwners": false,
              "discoverySettings": { "showInTeamsSearchAndSuggestions": true },
              "memberSettings": {
              "allowCreateUpdateChannels": true,
              "allowCreateUpdateRemoveConnectors": true
           },
           "guestSettings": {
              "allowCreateUpdateChannels": true,
              "allowDeleteChannels": false
            },
            "messagingSettings": {
              "allowUserEditMessages": true,
              "allowChannelMentions": true
            },
            "funSettings": {
              "allowGiphy": true,
              "allowCustomMemes": true
            }
          }    }  ]
        }

I am trying to read the "body" field using the code below (json is read in boost::property_tree::ptree jsonBatchResponse jsonBatchResponse). But strBody is empty and it doesn't read the "Body" field correctly. :

enter code here
     for (auto& v : jsonBatchResponse.get_child("responses"))
     {       
        std::string strID = v.second.get<std::string>("id", "");
        std::string strStatus = v.second.get<std::string>("status", "");
        std::string strBody = v.second.get<std::string>("body", "");
     }

It looks like v.second.getstd::string("body", "") is not the right way to read the JSON field. Is there any other way available (other than reading individual fields in the JSON value)? Please let me know.

user13260866
  • 131
  • 1
  • 2
  • 9

1 Answers1

0

The body is not a string.

So, getting the child object would be in order:

for (auto const& v : jsonBatchResponse.get_child("responses")) {
    std::string  strID     = v.second.get<std::string>("id", "");
    std::string  strStatus = v.second.get<std::string>("status", "");
    ptree const& body      = v.second.get_child("body");
}

If you add some output to that loop with e.g.

    std::cout << std::quoted(strID) << "\n";
    std::cout << std::quoted(strStatus) << "\n";
    write_json(std::cout, body);

It will print Live On Coliru

"1"
"200"
{
    "createdDateTime": "2021-04-22T09:24:59.394Z",
    "displayName": "Test1",
    "visibility": "public",
    "isMembershipLimitedToOwners": "false",
    "discoverySettings": {
        "showInTeamsSearchAndSuggestions": "true"
    },
    "memberSettings": {
        "allowCreateUpdateChannels": "true",
        "allowCreateUpdateRemoveConnectors": "true"
    },
    "guestSettings": {
        "allowCreateUpdateChannels": "true",
        "allowDeleteChannels": "false"
    },
    "messagingSettings": {
        "allowUserEditMessages": "true",
        "allowChannelMentions": "true"
    },
    "funSettings": {
        "allowGiphy": "true",
        "allowCustomMemes": "true"
    }
}

BONUS: Using a proper JSON library instead

Boost Property Tree is NOT a JSON library, and therefore has a lot of limitations.

Instead I suggest using Boost JSON:

Live On Coliru

#include <boost/json.hpp>
#include <boost/json/src.hpp>
#include <iostream>

namespace json = boost::json;

extern std::string sample;

int main() {
    json::object jsonBatchResponse = json::parse(sample).as_object();

    for (auto& v : jsonBatchResponse["responses"].as_array()) {
        auto& res = v.as_object();
        json::value id  = res["id"],     // string
            status      = res["status"], // integer
            body        = res["body"];   // object
        std::cout << id << "\n";
        std::cout << status << "\n";
        std::cout << body << "\n";
    }
}

std::string sample = R"(
{
    "responses": [{
        "id": "1",
        "status": 200,
        "headers": {
            "OData-Version": "4.0",
            "Content-Type": "application/json;odata.metadata=minimal;odata.streaming=true"
        },
        "body": {
            "createdDateTime": "2021-04-22T09:24:59.394Z",
            "displayName": "Test1",
            "visibility": "public",
            "isMembershipLimitedToOwners": false,
            "discoverySettings": {
                "showInTeamsSearchAndSuggestions": true
            },
            "memberSettings": {
                "allowCreateUpdateChannels": true,
                "allowCreateUpdateRemoveConnectors": true
            },
            "guestSettings": {
                "allowCreateUpdateChannels": true,
                "allowDeleteChannels": false
            },
            "messagingSettings": {
                "allowUserEditMessages": true,
                "allowChannelMentions": true
            },
            "funSettings": {
                "allowGiphy": true,
                "allowCustomMemes": true
            }
        }
    }]
}
)";

Prints

"1"
200
{"createdDateTime":"2021-04-22T09:24:59.394Z","displayName":"Test1","visibility":"public","isMembershipLimitedToOwners":false,"discoverySettings":{"showInTeamsSearchAndSuggestions":true},"memberSettings":{"allowCreateUpdateChannels":true,"allowCreateUpdateRemoveConnectors":true},"guestSettings":{"allowCreateUpdateChannels":true,"allowDeleteChannels":false},"messagingSettings":{"allowUserEditMessages":true,"allowChannelMentions":true},"funSettings":{"allowGiphy":true,"allowCustomMemes":true}}
sehe
  • 374,641
  • 47
  • 450
  • 633