'json config reader in C++

I have this config data in this json,

{
    "difficulty":-1,
    "damage":100,
    "infinite":true,
    "tilewidth":16,
    "type":"map",
    "version":"1.2.4"
}

and i want to store these variables in my program.I cant use a Map cause there isn't a fixed type to read (int,string,bool)...

using JSON = nlohmann::json;
/* struct Configs final {
  int difficulty;
  int damage;
  bool infinite;
  int tilewidth;
  std::string type;
std::string version;

}; */
int main(void) {
  JSON j;
  std::ifstream in("./assets/Map.json");
  in >> j;
  for (auto &el : j.items()) {
    std::cout << el.key() << " : " << el.value() << "\n";
  }
  return 0;
}

What are some smart ways of doing this?



Solution 1:[1]

I prefer to provide a from_json function. It could look like this:

struct Configs final {
    int difficulty;
    int damage;
    bool infinite;
    int tilewidth;
    std::string type;
    std::string version;
};

void from_json(const json& j, Configs& c) {
    j.at("difficulty").get_to(c.difficulty);
    j.at("damage").get_to(c.damage);
    j.at("infinite").get_to(c.infinite);
    j.at("tilewidth").get_to(c.tilewidth);
    j.at("type").get_to(c.type);
    j.at("version").get_to(c.version);
}

You could then populate a Configs like this:

in >> j;
auto conf = j.get<Configs>();

Solution 2:[2]

You're gonna have to dig into the documentation for your JSON library. Figure out how to check the types of each member you've parsed. Docs here recommend making a from_json function for your class/struct type. It looks like they provide some helpful macros for connecting JSON fields to your class/struct fields, like NLOHMANN_DEFINE_TYPE_NON_INSTRUSIVE

This seems to work alright

I'm assuming from_json is going to throw. Make sure you handle errors.

#include <string>
#include <nlohmann/json.hpp>
using namespace std::string_literals;

static const auto sampleJson = R"(
{
    "difficulty":-1,
    "damage":100,
    "infinite":true,
    "tilewidth":16,
    "type":"map",
    "version":"1.2.4"
}
)"s;

struct Configs final {
  int difficulty;
  int damage;
  bool infinite;
  int tilewidth;
  std::string type;
  std::string version;
};

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Configs, difficulty, damage, infinite, tilewidth, type, version);

using JSON = nlohmann::json;
int main(void) 
{
  try {
    auto j = JSON::parse(sampleJson);
    Configs c;
    from_json(j, c);
  }
  catch (...) {
      return 1;
  }

  return 0;
}

Solution 3:[3]

You can use my command line tool json-cpp-gen to automatically generate a JSON parser class from the Configs structure definition. (It might not recognize the final keyword so you might have to remove that.) All you have to do is pass it a configuration file containing

{
    "inputs": [ "Configs.h" ],
    "parsers": [ {
        "name": "ConfigsParser",
        "types": [ "Configs" ],
        "headerOutput": "ConfigsParser.h",
        "sourceOutput": "ConfigsParser.cpp"
    } ],
}

where Configs.h is the relative path to the file where the sturcture is defined and then you can use the generated parser class as ConfigsParser::parse(configsOutput, jsonString);.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 Detheroc