我正在处理一种加密货币RPC,并接收json数据,如下所示:
{
...
"amount": 1.34000000,
"confirmations": 230016,
"spendable": true,
"solvable": true
...
}
使用Jsoncpp库或json11获取解析为double
的数字。发生这种情况时,由于双重精度问题,结果为:1.3400000000000001
。总的来说,这对金融交易造成了灾难性的影响,并且是不可接受的。
我已经有一个定点库,可以使用有效的字符串并将其在内部视为整数。有没有办法让Jsoncpp(或其他任何json库)将选定的数字json值用作字符串,以便我可以使用固定精度正确对待它们?
答案 0 :(得分:1)
json库中似乎没有解决方案,因此我必须自己修改数字并用引号将其包装。我将此功能应用于响应。
[](std::string& jsonStr) {
// matches "amount" field in json
static std::regex reg(R"((\s*\"amount\"\s*:)\s*(\d*\.{0,1}\d{0,8})\s*)");
jsonStr = std::regex_replace(jsonStr, reg, "$1\"$2\"");
};
现在它可以正常工作了。
答案 1 :(得分:0)
我喜欢ThorsSerializer。免责声明是我写的。
它支持您正在寻找的东西。
您可以告诉解析器为类使用标准的输入/输出运算符(然后您可以自己定义)。
示例:
#include "ThorSerialize/JsonThor.h"
#include "ThorSerialize/SerUtil.h"
#include <sstream>
#include <iostream>
#include <string>
#include <map>
struct FixedPoint
{
int integerPart;
int floatPart;
friend std::istream& operator>>(std::istream& stream, FixedPoint& data)
{
// This code assumes <number>.<number>
// Change to suite your needs.
char c;
stream >> data.integerPart >> c >> data.floatPart;
if (c != '.')
{
stream.setstate(std::ios::failbit);
}
return stream;
}
};
// This declaration tells the serializer to use operator>> for reading
// and operator<< for writing this value.
// Note: The value must still conform to standard Json type
// true/false/null/integer/real/quoted string
ThorsAnvil_MakeTraitCustom(FixedPoint);
struct BitCoin
{
FixedPoint amount;
int confirmations;
bool spendable;
bool solvable;
};
// This declaration tells the serializer to use the standard
// built in operators for a struct and serialize the listed members.
// There are built in operations for all built in types and std::Types
ThorsAnvil_MakeTrait(BitCoin, amount, confirmations, spendable, solvable);
用法示例:
int main()
{
using ThorsAnvil::Serialize::jsonImport;
using ThorsAnvil::Serialize::jsonExport;
std::stringstream file(R"(
{
"amount": 1.34000000,
"confirmations": 230016,
"spendable": true,
"solvable": true
}
)");
BitCoin coin;
file >> jsonImport(coin);
std::cout << coin.amount.integerPart << " . " << coin.amount.floatPart << "\n";
}
内部版本:
> g++ -std=c++1z 51087868.cpp -lThorSerialize17
答案 2 :(得分:-1)
本机jsoncpp解决方案用于RTFM !!! (例如,这里:https://open-source-parsers.github.io/jsoncpp-docs/doxygen/class_json_1_1_stream_writer_builder.html)
Json::StreamWriterBuilder builder;
builder["commentStyle"] = "None";
builder["indentation"] = " ";
builder["precision"] = 15;
这将设置您的编写器浮点精度,以避免在双精度表示形式中打印小的截断错误。例如,代替json字段
“金额”:1.3400000000000001,
您现在将获得
“金额”:1.340000000000000,
根据需要。