Search code examples
c++jsonnlohmann-json

Detect with "JSON for Modern C++" library that integer doesn't fit into a specified type?


This code prints -1:

#include <iostream>
#include <nlohmann/json.hpp>

int main()
{
    auto jsonText = "{ \"val\" : 4294967295 }";
    auto json = nlohmann::json::parse(jsonText);
    std::cout << json.at("val").get<int>() << std::endl;
}

I would like to detect that the value is out of the expected range. Is it possible to accomplish somehow?


Solution

  • Aside Holt's answer, you can also take advantage of the operator== the library defines, which states:

    Integer and floating-point numbers are automatically converted before comparison. Note than two NaN values are always treated as unequal.

    What happens here is that the number overflows, which means json["val"] != json["val"].get<int>().Disclaimer: I have no idea how efficient this approach is compared to Holt's approach

    #include <iostream>
    #include <nlohmann/json.hpp>
    
    int main()
    {
        auto jsonText = "{ \"val\" : 4294967296 }";
        auto json = nlohmann::json::parse(jsonText);
        auto val = json["val"].get<long long>();
        auto i = json["val"].get<int>();
        bool longOverflow = json["val"] != val;
        bool intOverflow = json["val"] != i;
        std::cout << std::boolalpha << "Long: " << longOverflow << "\nInt: " << intOverflow;
    }
    

    Prints:

    Long: false
    Int: true
    

    Try it online

    Note that this has a caveat: If the value stored in the JSON is a double or a float, and is retrieved as a long or int, it'll naturally evaluate to true (12.3 != 12), but it doesn't have to imply an overflow. You can check the general type with is_number_integer() (checks for int, long, and various other types, unsigned or signed) and is_number_float() (checks for double/float).

    From what I can tell though, from int/long to double doesn't fail. However, provided a big enough number, the library will fail to parse the number (json.exception.out_of_range.406), so there's a hard limit imposed by the library. From what I can tell, that limit is set at 1.79769e+308 (at least on Wandbox), or the max double value. This also makes double the only type you can't overflow with the library.

    As far as automatically checking for number overflow when you retrieve it with a certain type, that's not supported out of the box.