I'm using nlohmann json to parse a config.json
file. The file will be modified by other developers, who use my code.
try {
conf.x1 = data.at("x1");
conf.x2 = data.at("x2");
// ...
conf.xN = data.at("xN");
} catch (const nlohmann::json::out_of_range &e) {
std::cerr << "Error. " << e.what() << std::endl;
return std::nullopt;
} catch (const nlohmann::json::type_error &e) {
std::cerr << "Error. " << e.what() << std::endl;
return std::nullopt;
}
nlohmann::json::out_of_range
exception, the e.what()
reads: [json.exception.out_of_range.403] key 'x1' not found
nlohmann::json::type_error
exception, it's [json.exception.type_error.302] type must be number, but is string
In the 1st case it easily tells the user that the value x1
is expected, but not found, even though I catch
over the whole block. For the 2nd case there are no hints which entry caused the error, forcing the user to search through the whole file.
I thought about writing a function that does the try-catch, e.g. int read_data(const std::string key)
, but the return values are different, which I guess could be solved with templates or writing a function for each type.
As this complicates the code, I first wanted to find out if there is a simpler alternative, similar to the out_of_range
exception.
Found the answer while writing this question:
In the FAQ it says to define JSON_DIAGNOSITCS
. Reading further:
As this global context comes at the price of storing one additional pointer per JSON value and runtime overhead to maintain the parent relation, extended diagnostics are disabled by default. They can, however, be enabled by defining the preprocessor symbol JSON_DIAGNOSTICS to 1 before including json.hpp.
Thus, while debugging, add the define before the include. For example, simply #ifdef
for a debug flag to decide if we want diagnostics. When using CMake, instead passing -D JSON_DIAGNOSTICS=1
on the command line enables the option project-wide.
#define JSON_DIAGNOSTICS 1
#include <nlohmann/json.hpp>