Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] Access multi-level json objects #1086

Closed
SimplyLiz opened this issue May 13, 2018 · 2 comments
Closed

[Question] Access multi-level json objects #1086

SimplyLiz opened this issue May 13, 2018 · 2 comments

Comments

@SimplyLiz
Copy link

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)?

@nlohmann
Copy link
Owner

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

@SimplyLiz
Copy link
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants