json: Value throws on null string

Take for example { "key" : null }.

Using value("key", "") on a null string throws [json.exception.type_error.302] type must be string, but is null.

Expected behavior : Use default value.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 18 (6 by maintainers)

Most upvoted comments

@2beens you can use a parse indirection for your data types to deal with these issues. This has the nice side effect of being easily extensible with if constexpr and friends.

template <class T>
inline void get_v(const nlohmann::json& j, const char* key, T& val) {
	if (j.at(key).is_null()) {
		val = T{};
	} else {
		val = j.value(key, T{});
	}
}

@Luperco not the best but possible workaround, just before NLOHMANN_DEFINE_TYPE_INTRUSIVE redefine NLOHMANN_JSON_FROM

// ignore null and missing fields
#undef NLOHMANN_JSON_FROM
#define NLOHMANN_JSON_FROM(v1) {\
auto iter = nlohmann_json_j.find(#v1);\
if (iter != nlohmann_json_j.end())\
    if (!iter->is_null())\
        iter->get_to(nlohmann_json_t.v1); }

I fear there is no easier solution than to manually filter the array at key “eventToken” from elements that are not strings.

Example (using https://en.wikipedia.org/wiki/Erase–remove_idiom):

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

using json = nlohmann::json;

int main() {
    json j = {"foo", nullptr, "bar", 1};
    j.erase(std::remove_if(j.begin(), j.end(), [](json& el) { return not el.is_string(); }), j.end());
    std::cout << j << std::endl;
}

Output:

["foo","bar"]

I guessed that much, I would like to challenge that however 😉

In a perfect world where API makers would follow the JSON spec perfectly, the current solution would work great. However, reality is quite different. I don’t see any downsides to modifying value to deal with this sort of issue. get<> offers a great alternative if you want to deal with exceptions.

Note that with the current behavior, one would need to check every single string for null. Which is madness when using huge APIs. Since if an end-point returns null for 1 empty string, it means any string may be null.

Willing to discuss changing value behavior?