Json writer, emit full precision for floating point Number types
Previously Qt JSON writer would only emit 6 digits of precision as this is the default with the formatter. However with testing against NodeJS JSON.stringify() this behavior is inconsistent with the defacto standard JSON implementation and conveys a loss of precision. Change-Id: Ie1845a6e0ee0b4c05f63ec0062f372e891855f0b Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
e2d614b6a9
commit
6348de8737
@ -63,6 +63,7 @@
|
||||
#include <qnumeric.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <limits>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
@ -171,8 +171,8 @@ static void valueToJson(const QJsonPrivate::Base *b, const QJsonPrivate::Value &
|
||||
break;
|
||||
case QJsonValue::Double: {
|
||||
const double d = v.toDouble(b);
|
||||
if (qIsFinite(d))
|
||||
json += QByteArray::number(d);
|
||||
if (qIsFinite(d)) // +2 to format to ensure the expected precision
|
||||
json += QByteArray::number(d, 'g', std::numeric_limits<double>::digits10 + 2); // ::digits10 is 15
|
||||
else
|
||||
json += "null"; // +INF || -INF || NaN (see RFC4627#section2.4)
|
||||
break;
|
||||
|
@ -96,6 +96,7 @@ private Q_SLOTS:
|
||||
|
||||
void toJson();
|
||||
void toJsonSillyNumericValues();
|
||||
void toJsonLargeNumericValues();
|
||||
void fromJson();
|
||||
void fromJsonErrors();
|
||||
void fromBinary();
|
||||
@ -1110,6 +1111,57 @@ void tst_QtJson::toJsonSillyNumericValues()
|
||||
QCOMPARE(json, expected);
|
||||
}
|
||||
|
||||
void tst_QtJson::toJsonLargeNumericValues()
|
||||
{
|
||||
QJsonObject object;
|
||||
QJsonArray array;
|
||||
array.append(QJsonValue(1.234567)); // actual precision bug in Qt 5.0.0
|
||||
array.append(QJsonValue(1.7976931348623157e+308)); // JS Number.MAX_VALUE
|
||||
array.append(QJsonValue(5e-324)); // JS Number.MIN_VALUE
|
||||
array.append(QJsonValue(std::numeric_limits<double>::min()));
|
||||
array.append(QJsonValue(std::numeric_limits<double>::max()));
|
||||
array.append(QJsonValue(std::numeric_limits<double>::epsilon()));
|
||||
array.append(QJsonValue(std::numeric_limits<double>::denorm_min()));
|
||||
array.append(QJsonValue(0.0));
|
||||
array.append(QJsonValue(-std::numeric_limits<double>::min()));
|
||||
array.append(QJsonValue(-std::numeric_limits<double>::max()));
|
||||
array.append(QJsonValue(-std::numeric_limits<double>::epsilon()));
|
||||
array.append(QJsonValue(-std::numeric_limits<double>::denorm_min()));
|
||||
array.append(QJsonValue(-0.0));
|
||||
object.insert("Array", array);
|
||||
|
||||
QByteArray json = QJsonDocument(object).toJson();
|
||||
|
||||
QByteArray expected =
|
||||
"{\n"
|
||||
" \"Array\": [\n"
|
||||
" 1.234567,\n"
|
||||
" 1.7976931348623157e+308,\n"
|
||||
// ((4.9406564584124654e-324 == 5e-324) == true)
|
||||
// I can only think JavaScript has a special formatter to
|
||||
// emit this value for this IEEE754 bit pattern.
|
||||
" 4.9406564584124654e-324,\n"
|
||||
" 2.2250738585072014e-308,\n"
|
||||
" 1.7976931348623157e+308,\n"
|
||||
" 2.2204460492503131e-16,\n"
|
||||
" 4.9406564584124654e-324,\n"
|
||||
" 0,\n"
|
||||
" -2.2250738585072014e-308,\n"
|
||||
" -1.7976931348623157e+308,\n"
|
||||
" -2.2204460492503131e-16,\n"
|
||||
" -4.9406564584124654e-324,\n"
|
||||
" 0\n"
|
||||
" ]\n"
|
||||
"}\n";
|
||||
|
||||
QCOMPARE(json, expected);
|
||||
|
||||
QJsonDocument doc;
|
||||
doc.setObject(object);
|
||||
json = doc.toJson();
|
||||
QCOMPARE(json, expected);
|
||||
}
|
||||
|
||||
void tst_QtJson::fromJson()
|
||||
{
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user