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 - how to find an object in an array #1331

Closed
SimplyLiz opened this issue Nov 2, 2018 · 3 comments
Closed

Question - how to find an object in an array #1331

SimplyLiz opened this issue Nov 2, 2018 · 3 comments
Labels
kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation

Comments

@SimplyLiz
Copy link

I want to store multiple images (with different attributes) per tile-type and find the correct json object that matches a key.
like:

Type floor, orientation: center

for (auto it : TileDataJSON["floor"].items()) {
  cout << "key " << it.key() << " and val " <<it.value();

}

Output:

key 0 and val {"image":"floor_0.png","orientation":"flat"}
key 1 and val {"image":"floor_center.png","orientation":"center"}
key 2 and val {"image":"floor_n.png","orientation":"n"}
....

Which makes sense.

If i try to access
TileDataJSON["floor"][it.key()]
i get an exception. ( i think it's because it.key is a string an not an int...

My (simplified) JSON File looks like this:

  "floor": [
    {
      "image": "floor_0.png",
      "orientation": "flat"
    },
    {
      "image": "floor_center.png",
      "orientation": "center"
    }
  ]
}```

What is the correct way to find the correct object of a type by an attribute?
@SimplyLiz
Copy link
Author

SimplyLiz commented Nov 2, 2018

After trying to figure out a way to do that, i came up with following solution:

  std::string findOrientation = "center";
  size_t idx = 0;
  while (!TileDataJSON["floor"][idx].is_null())
  {
    for (auto &it : TileDataJSON["floor"][idx].items())
    {
      if (it.key() == "orientation" && it.value() == findOrientation)
      {
        if (!TileDataJSON["floor"][idx]["image"].is_null())
        {
        std::cout << "Filename = " << TileDataJSON["floor"][idx]["image"].get<std::string>();
        }
      }
    }
    idx++;
  }

It does work, but is there a better solution?

@nlohmann
Copy link
Owner

nlohmann commented Nov 2, 2018

Here is a more elegant approach using std::find_if:

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

using json = nlohmann::json;

int main()
{
    json j = R"([
    {
        "image": "floor_0.png",
        "orientation": "flat"
    },
    {
        "image": "floor_center.png",
        "orientation": "center"
    }
    ])"_json;
    
    auto res = std::find_if(j.begin(), j.end(), [](const json& x) {
        auto it = x.find("orientation");
        return it != x.end() and it.value() == "center";

        // alternative approach using value member function
        // return x.is_object() and x.value("orientation", "") == "center";
    });
    
    std::cout << *res << std::endl;
}

@nlohmann nlohmann added the solution: proposed fix a fix for the issue has been proposed and waits for confirmation label Nov 2, 2018
@SimplyLiz
Copy link
Author

Thank you! I llike that approach. Maybe you could add that to the documentation too?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Projects
None yet
Development

No branches or pull requests

2 participants