如何通过nlohmann::json解析得到std::string形式的数字


#include <iostream>
#include <string>
#include <limits>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
std::cout.precision(std::numeric_limits<double>::max_digits10);
// create a JSON value with different types
json json_types =
{
{"number_b", 1234567890.0123456789}
};
std::cout << std::fixed << json_types.dump(4) << std::endl;
auto v2 = json_types["number_b"].get<double>();
std::cout << "number_b in double: " << std::fixed << v2 << std::endl;
// auto v3 = json_types["number_b"].get<std::string>();  
// [json.exception.type_error.302] type must be string, but is number
}

输出:

{
"number_b": 1234567890.0123458
}
number_b in double: 1234567890.01234579086303711

有没有一种方法可以在"1234567890.0123456789"的原始输入值的基础上获得number_b的值作为std::string

注意:JSON数值是通过第三方传递的,我无法将输入值从数字更改为源代码中的字符串。

double的精度约为小数点后15-17位[1]。double无法准确存储1234567890.0123456789,因此,如果先将其存储到double中,则无法将其转换为准确的字符串。

您可以尝试挂接sax接口[2],该接口是nlohmann库提供的(更具体地说是number_float()(函数,用于获取解析期间json中存在的原始字符串。

然而,我不会依赖这些技巧。使用浮点数字本质上是不准确的,最好只是看看这个数字是在一个小范围内还是类似的范围内。然而,这取决于您试图解决的确切问题。

这是不可能的。

  1. 上面的例子在编译时丢失了精度
  2. RFC7159.从技术上讲,你不应该接收这样的JSON作为输入源,因为发送这样的JSON编号的软件通常符合IEEE 754-2008

JSON编号,如1E400或3.141592653589793238462643383279,可能表明存在潜在的互操作性问题,因为这表明创建它的软件希望接收软件在数值大小和精度方面比广泛可用的软件具有更大的能力。

目前没有简单的方法。

您需要实现自己的SAX解析器。

参见:

  • https://github.com/nlohmann/json/discussions/3432
  • https://github.com/nlohmann/json/issues/642

如果您考虑切换到允许此类操作的其他JSON库,请使用RAPID JSON。

const auto& document = parser.Parse<rapidjson::kParseNumbersAsStringsFlag>(data.data(), data.length());

最新更新