c++jsonrapidjsontiled

How to parse JSON array from inside an object with rapidjson


The following is a JSON file exported from Tiled Map Editor.

{ "compressionlevel":-1,
 "height":32,
 "infinite":false,
 "layers":[
        {
         "data":[ A whole bunch of integers in here],
         "height":32,
         "id":1,
         "name":"Tile Layer 1",
         "opacity":1,
         "type":"tilelayer",
         "visible":true,
         "width":32,
         "x":0,
         "y":0
        }],
 "nextlayerid":2,
 "nextobjectid":1,
 "orientation":"orthogonal",
 "renderorder":"right-down",
 "tiledversion":"1.7.2",
 "tileheight":32,
 "tilesets":[
        {
         "firstgid":1,
         "source":"..\/..\/..\/..\/Desktop\/tileset001.tsx"
        }],
 "tilewidth":32,
 "type":"map",
 "version":"1.6",
 "width":32
}

And in this C++ block I am trying to parse out the data I actually need.

std::ifstream inFStream(filePath, std::ios::in);
    if(!inFStream.is_open())
    {
        printf("Failed to open map file: &s", filePath);
    }

    rapidjson::IStreamWrapper inFStreamWrapper{inFStream};
    rapidjson::Document doc{};
    doc.ParseStream(inFStreamWrapper);

    _WIDTH = doc["width"].GetInt();   //get width of map in tiles
    _HEIGHT = doc["height"].GetInt(); //get height of map in tiles

    const rapidjson::Value& data = doc["layers"]["data"]; //FAILURE POINT
    assert(data.IsArray());

When I compile I am able to extract the right value for width and height which are outside of "layers" :[{}] But when that const rapidjson::Value& data = doc["layers"]["data"]; gets called I get a runtime error claiming that document.h line 1344 IsObject() Assertion Failed.

Ive been up and down the rapidjson website and other resources and cant find anything quite like this.

The next step would be to get the int values stored in "data" and push them into a std::vector but thats not going to happen till I figure out how to get access to "data"


Solution

  • doc['layers'] is an array.

    const rapidjson::Value& layers = doc["layers"];
    assert(layers.IsArray()); 
    
    for (size_t i=0; i < layers.Size(); i++) {
      const rapidjson::Value& data = doc["layers"][i]["data"];
      assert(data.IsArray());
    }
    

    UPDATE:

    Direct access to first data item in layers:

    const rapidjson::Value& data = doc["layers"][0]["data"];
    

    This only gives you the data for the first item in layers array. If layers have at least one item and you only need the first one, then this will always work.