2

I have the following function:

// get-function that can handle nullptr.
template <typename T>
static const T get(const nlohmann::json& json, const T& retOnNull = T())
{
    return json.is_null() ? retOnNull : json.get<T>();
}

Then I call it like this:

nlohmann::json j;

// ...
// Load json from file into j

auto ret = get<std::string>(j["SomeKey"], "");

Now I would expect one of three things to happen:

  1. If "SomeKey" exists and is a string it should return that value
  2. If "SomeKey" doesn't exist it should first be created with null as default value and then sent into the function which should return an empty string as it received a null value
  3. If "SomeKey" existed but wasn't a string it should throw a json.exception.type_error.302

Instead I sometimes (randomly) get the json.exception.type_error.302 exception even though, in my case, "SomeKey" doesn't exist. I checked what happens at that point and the data sent into the get function seems to be not null and of type 105 (which is an indication the data is undefined). So how can this call into this function yield undefined data? Is it something about the new json entry going out of scope due to the reference pointer? Why does it happen randomly and not consistently? Is this an invalid way of using a new key?

DaedalusAlpha
  • 1,610
  • 4
  • 20
  • 33

1 Answers1

0

The code is invoking undefined behavior: https://json.nlohmann.me/api/basic_json/operator%5B%5D/#template-parameters

If the element with key key does not exist, the behavior is undefined and is guarded by a runtime assertion!

Use json::at() instead so you get a proper error (by exception) when the key doesn't exist or a type mismatch was detected.

Alternatively, use json::contains() to check if the key is legal to access before attempting to access it: https://json.nlohmann.me/api/basic_json/contains/

If j.contains(x) returns true for a key or JSON pointer x, then it is safe to call j[x].

Ext3h
  • 5,713
  • 17
  • 43
  • A) There is no runtime assertion happening B) "If key is not found in the object, then it is silently added to the object and filled with a null value to make key a valid reference. In case the value was null before, it is converted to an object." C) I believe that warning you talk about is if the json value is const, which it isn't in this case. – DaedalusAlpha Apr 11 '23 at 11:54
  • Ok, this is actually the correct answer. I didn't think my `json j` was const, but it actually was, which means the error I'm receiving makes perfect sense, as per this answer. – DaedalusAlpha Apr 11 '23 at 13:32