Json: Question - how to find an object in an array

Created on 2 Nov 2018  路  3Comments  路  Source: nlohmann/json

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?

question proposed fix

Most helpful comment

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;
}

All 3 comments

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?

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;
}

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

Was this page helpful?
0 / 5 - 0 ratings