From 57acf1b46ca4bb670f4bf1fe3807dfa91edb6248 Mon Sep 17 00:00:00 2001 From: Liang Qi <liang.qi@digia.com> Date: Tue, 14 May 2013 14:19:47 +0200 Subject: [PATCH] QtCore: fix the number precision in QJsonDocument.toJson() In JSON, any number is stored in double. We need to make sure we keep the maximum possible number precision for integer number. In IEEE 754 double format, the significand precision is 53 bits(52 explicityly stored). Autotest is included. qint64 and double work fine. Task-number: QTBUG-28467 Change-Id: I7f857671c50e4334e9329c778f9b4f090f490540 Reviewed-by: Sune Vuorela <sune@vuorela.dk> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> --- src/corelib/json/qjsonwriter.cpp | 2 +- tests/auto/corelib/json/tst_qtjson.cpp | 77 ++++++++++++++++++++++---- 2 files changed, 66 insertions(+), 13 deletions(-) diff --git a/src/corelib/json/qjsonwriter.cpp b/src/corelib/json/qjsonwriter.cpp index 76f62241e34..b09c6dd5358 100644 --- a/src/corelib/json/qjsonwriter.cpp +++ b/src/corelib/json/qjsonwriter.cpp @@ -170,7 +170,7 @@ static void valueToJson(const QJsonPrivate::Base *b, const QJsonPrivate::Value & json += v.toBoolean() ? "true" : "false"; break; case QJsonValue::Double: - json += QByteArray::number(v.toDouble(b)); + json += QByteArray::number(v.toDouble(b), 'g', 13); break; case QJsonValue::String: json += '"'; diff --git a/tests/auto/corelib/json/tst_qtjson.cpp b/tests/auto/corelib/json/tst_qtjson.cpp index 6811551769c..fc4b3831c4e 100644 --- a/tests/auto/corelib/json/tst_qtjson.cpp +++ b/tests/auto/corelib/json/tst_qtjson.cpp @@ -231,9 +231,54 @@ void tst_QtJson::testNumbers() QJsonArray array; for (int i = 0; i < n; ++i) array.append((double)numbers[i]); + + QByteArray serialized = QJsonDocument(array).toJson(); + QJsonDocument json = QJsonDocument::fromJson(serialized); + QJsonArray array2 = json.array(); + + QCOMPARE(array.size(), array2.size()); + for (int i = 0; i < array.size(); ++i) { + QCOMPARE(array.at(i).type(), QJsonValue::Double); + QCOMPARE(array.at(i).toDouble(), (double)numbers[i]); + QCOMPARE(array2.at(i).type(), QJsonValue::Double); + QCOMPARE(array2.at(i).toDouble(), (double)numbers[i]); + } + } + + { + qint64 numbers[] = { + 0, + -1, + 1, + (1UL<<54), + (1UL<<55), + (1UL<<56), + -(1UL<<54), + -(1UL<<55), + -(1UL<<56), + (1UL<<54) - 1, + (1UL<<55) - 1, + (1UL<<56) - 1, + -((1UL<<54) - 1), + -((1UL<<55) - 1), + -((1UL<<56) - 1) + }; + int n = sizeof(numbers)/sizeof(qint64); + + QJsonArray array; + for (int i = 0; i < n; ++i) + array.append((double)numbers[i]); + + QByteArray serialized = QJsonDocument(array).toJson(); + QJsonDocument json = QJsonDocument::fromJson(serialized); + QJsonArray array2 = json.array(); + + QCOMPARE(array.size(), array2.size()); for (int i = 0; i < array.size(); ++i) { QCOMPARE(array.at(i).type(), QJsonValue::Double); QCOMPARE(array.at(i).toDouble(), (double)numbers[i]); + QCOMPARE(array2.at(i).type(), QJsonValue::Double); + QCOMPARE(array2.at(i).toDouble(), (double)numbers[i]); } } @@ -242,18 +287,18 @@ void tst_QtJson::testNumbers() 0, -1, 1, - (1<<26), - (1<<27), - (1<<28), - -(1<<26), - -(1<<27), - -(1<<28), - (1<<26) - 1, - (1<<27) - 1, - (1<<28) - 1, - -((1<<26) - 1), - -((1<<27) - 1), - -((1<<28) - 1), + (1UL<<54), + (1UL<<55), + (1UL<<56), + -(1UL<<54), + -(1UL<<55), + -(1UL<<56), + (1UL<<54) - 1, + (1UL<<55) - 1, + (1UL<<56) - 1, + -((1UL<<54) - 1), + -((1UL<<55) - 1), + -((1UL<<56) - 1), 1.1, 0.1, -0.1, @@ -266,9 +311,17 @@ void tst_QtJson::testNumbers() QJsonArray array; for (int i = 0; i < n; ++i) array.append(numbers[i]); + + QByteArray serialized = QJsonDocument(array).toJson(); + QJsonDocument json = QJsonDocument::fromJson(serialized); + QJsonArray array2 = json.array(); + + QCOMPARE(array.size(), array2.size()); for (int i = 0; i < array.size(); ++i) { QCOMPARE(array.at(i).type(), QJsonValue::Double); QCOMPARE(array.at(i).toDouble(), numbers[i]); + QCOMPARE(array2.at(i).type(), QJsonValue::Double); + QCOMPARE(array2.at(i).toDouble(), numbers[i]); } } -- GitLab