Json: [Question] Access multi-level json objects

Created on 13 May 2018  路  2Comments  路  Source: nlohmann/json

Sry for posting a question here, but you don't have a forum and i couldn't figure out how to do this properly.

For my game, i want to store information about sprites in a json file.
First Level - Sprite type (Terrain, Building, Water, ...)
Second Level - Sprite ID (Unique ID to access sprites)
Third Level - Detail Information (Filename, which can vary)

My Implementation:

  #include <iostream>
  #include <nlohmann/json.hpp>

  using json = nlohmann::json;

  void accessTileData(std::string TileType, int tileID);
  json _json;

  int main() {
      // create a JSON object

        _json["terrain"]["0"]["filename"] = std::string("images/floor/floor.png");
        _json["terrain"]["0"]["isPowered"] = true;
        _json["terrain"]["1"]["filename"] = std::string("images/floor/floor2.png");
        _json["terrain"]["1"]["isPowered"] = true;
        _json["terrain"]["2"]["filename"] = std::string("images/floor/floor3.png");
        _json["terrain"]["2"]["isPowered"] = true;
        _json["terrain"]["3"]["filename"] = std::string("images/floor/floor4.png");
        _json["terrain"]["3"]["isPowered"] = true;
        _json["buildings"]["4"]["filename"] = std::string("images/buildings/house1.png");
        _json["buildings"]["4"]["type"] = "building";
        _json["buildings"]["4"]["zone"] = "residential";

        accessTileData("terrain", 2);

  }


  void accessTileData(std::string TileType, int tileID) {
    for (json::iterator it = _json.begin(); it != _json.end(); ++it) {
      if (it.key() == TileType) {
        std::cout << "Terrain Tiles:\n\t" << it.value() << std::endl;            

              // This retrieves more then just the filename value
              std::string retrievedFileName = _json[it.key()][std::to_string(tileID)]["filename"].dump();
              std::cout << "Filename of Tile " << tileID  << std::endl << retrievedFileName;
              // Output:
              // Filename of Tile 2
              // "images/floor/floor3.png"  0  {"filename":"images/floor/floor.png","isPowered":true}


              // this does not work
        for (json::iterator it_meta = it.value().begin(); it_meta != it.value().end(); ++it) {
          std::cout << "\t" << it_meta.key() << "  " << it_meta.value() << std::endl;
        }
              // Error Message
              // prog.exe: ./nlohmann/json.hpp:4087: nlohmann::detail::iter_impl<BasicJsonType>::reference nlohmann::detail::iter_impl<BasicJsonType>::operator*() const [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::iter_impl<BasicJsonType>::reference = nlohmann::basic_json<>&]: Assertion `m_it.object_iterator != m_object->m_value.object->end()' failed.
      }
    }
  }

How do i properly retrieve all the informations of a tileID ?
Is there a possibility to retrieve a tile id (second key) from the json object without specifying the first key (type)?

question

Most helpful comment

I'm not sure what you mean. Maybe this helps, using the items() function:

#include <iostream>
#include "json.hpp"

using json = nlohmann::json;

int main() {
    json _json;
    _json["terrain"]["0"]["filename"] = std::string("images/floor/floor.png");
    _json["terrain"]["0"]["isPowered"] = true;
    _json["terrain"]["1"]["filename"] = std::string("images/floor/floor2.png");
    _json["terrain"]["1"]["isPowered"] = true;
    _json["terrain"]["2"]["filename"] = std::string("images/floor/floor3.png");
    _json["terrain"]["2"]["isPowered"] = true;
    _json["terrain"]["3"]["filename"] = std::string("images/floor/floor4.png");
    _json["terrain"]["3"]["isPowered"] = true;
    _json["buildings"]["4"]["filename"] = std::string("images/buildings/house1.png");
    _json["buildings"]["4"]["type"] = "building";
    _json["buildings"]["4"]["zone"] = "residential";

    // iterate the outer object
    for (auto& i : _json.items())
    {
        // iterate that object's items
        for (auto& j : i.value().items())
        {
            // output the keys
            std::cout << i.key() << " -> " << j.key() << std::endl;
        }
    }
}

Output:

buildings -> 4
terrain -> 0
terrain -> 1
terrain -> 2
terrain -> 3

All 2 comments

I'm not sure what you mean. Maybe this helps, using the items() function:

#include <iostream>
#include "json.hpp"

using json = nlohmann::json;

int main() {
    json _json;
    _json["terrain"]["0"]["filename"] = std::string("images/floor/floor.png");
    _json["terrain"]["0"]["isPowered"] = true;
    _json["terrain"]["1"]["filename"] = std::string("images/floor/floor2.png");
    _json["terrain"]["1"]["isPowered"] = true;
    _json["terrain"]["2"]["filename"] = std::string("images/floor/floor3.png");
    _json["terrain"]["2"]["isPowered"] = true;
    _json["terrain"]["3"]["filename"] = std::string("images/floor/floor4.png");
    _json["terrain"]["3"]["isPowered"] = true;
    _json["buildings"]["4"]["filename"] = std::string("images/buildings/house1.png");
    _json["buildings"]["4"]["type"] = "building";
    _json["buildings"]["4"]["zone"] = "residential";

    // iterate the outer object
    for (auto& i : _json.items())
    {
        // iterate that object's items
        for (auto& j : i.value().items())
        {
            // output the keys
            std::cout << i.key() << " -> " << j.key() << std::endl;
        }
    }
}

Output:

buildings -> 4
terrain -> 0
terrain -> 1
terrain -> 2
terrain -> 3

Thank you, that's no exactly what i was looking for but it helps!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jmlemetayer picture jmlemetayer  路  3Comments

qis picture qis  路  4Comments

bassosimone picture bassosimone  路  3Comments

MariaRamos89 picture MariaRamos89  路  4Comments

moneroexamples picture moneroexamples  路  4Comments