使用 "JSON for Modern C++" 库检测整数不适合指定类型?
Detect with "JSON for Modern C++" library that integer doesn't fit into a specified type?
此代码打印 -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;
}
我想检测该值超出预期范围。有可能以某种方式完成吗?
做你想做的唯一方法是实际检索一个更大的整数类型的值,然后检查该值是否在 int
.
的范围内
using integer_t = nlohmann::json::number_integer_t;
auto ivalue = json.at("val").get<integer_t>();
if (ivalue < std::numeric_limits<int>::min() || ivalue > std::numeric_limits<int>::max()) {
// Range error...
}
一些细节...
在调用 parse()
期间使用 std::strtoull
或 std::strtoll
(取决于是否存在 -
符号)解析数字,并转换为 nlohmann::json::number_integer_t
(int64_t
1) 或 nlohmann::json::number_unsigned_t
(uint64_t
1).
当您使用 get<int>
查询值时,唯一要做的就是将存储的 int64_t
/uint64_t
值转换为 int
,因此没有此时检查范围的方法。
此外,您无法检索原始 "string",因为仅存储了实际(无符号)整数值。
1 int64_t
和 uint64_t
是默认类型,因为 nlohmann::json
实际上是 [= 的别名27=] 模板(很像 std::string
),但你可以使用任何你想要的类型。
除了 Holt 的回答,您还可以利用库定义的 operator==
,其中指出:
Integer and floating-point numbers are automatically converted before comparison. Note than two NaN values are always treated as unequal.
这里发生的是数字溢出,这意味着 json["val"] != json["val"].get<int>()
。免责声明:我不知道这种方法与 Holt 的方法相比效率如何
#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;
}
打印:
Long: false
Int: true
请注意,这有一个警告:如果存储在 JSON 中的值是双精度或浮点数,并且作为 long 或 int 检索,它自然会评估为 true (12.3 != 12),但这并不一定意味着溢出。您可以使用 is_number_integer()
(checks for int, long, and various other types, unsigned or signed) and is_number_float()
检查一般类型(检查 double/float)。
据我所知,从 int/long 到 double 不会失败。但是,如果数字足够大,the library will fail to parse the number (json.exception.out_of_range.406
),那么库会施加一个硬性限制。据我所知,该限制设置为 1.79769e+308
(至少在 Wandbox 上),或最大双精度值。这也使 double 成为唯一不能随库溢出的类型。
至于当您使用某种类型检索数字时自动检查数字溢出,开箱即用不支持。
此代码打印 -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;
}
我想检测该值超出预期范围。有可能以某种方式完成吗?
做你想做的唯一方法是实际检索一个更大的整数类型的值,然后检查该值是否在 int
.
using integer_t = nlohmann::json::number_integer_t;
auto ivalue = json.at("val").get<integer_t>();
if (ivalue < std::numeric_limits<int>::min() || ivalue > std::numeric_limits<int>::max()) {
// Range error...
}
一些细节...
在调用 parse()
期间使用 std::strtoull
或 std::strtoll
(取决于是否存在 -
符号)解析数字,并转换为 nlohmann::json::number_integer_t
(int64_t
1) 或 nlohmann::json::number_unsigned_t
(uint64_t
1).
当您使用 get<int>
查询值时,唯一要做的就是将存储的 int64_t
/uint64_t
值转换为 int
,因此没有此时检查范围的方法。
此外,您无法检索原始 "string",因为仅存储了实际(无符号)整数值。
1 int64_t
和 uint64_t
是默认类型,因为 nlohmann::json
实际上是 [= 的别名27=] 模板(很像 std::string
),但你可以使用任何你想要的类型。
除了 Holt 的回答,您还可以利用库定义的 operator==
,其中指出:
Integer and floating-point numbers are automatically converted before comparison. Note than two NaN values are always treated as unequal.
这里发生的是数字溢出,这意味着 json["val"] != json["val"].get<int>()
。免责声明:我不知道这种方法与 Holt 的方法相比效率如何
#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;
}
打印:
Long: false
Int: true
请注意,这有一个警告:如果存储在 JSON 中的值是双精度或浮点数,并且作为 long 或 int 检索,它自然会评估为 true (12.3 != 12),但这并不一定意味着溢出。您可以使用 is_number_integer()
(checks for int, long, and various other types, unsigned or signed) and is_number_float()
检查一般类型(检查 double/float)。
据我所知,从 int/long 到 double 不会失败。但是,如果数字足够大,the library will fail to parse the number (json.exception.out_of_range.406
),那么库会施加一个硬性限制。据我所知,该限制设置为 1.79769e+308
(至少在 Wandbox 上),或最大双精度值。这也使 double 成为唯一不能随库溢出的类型。
至于当您使用某种类型检索数字时自动检查数字溢出,开箱即用不支持。