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>
bb10
Liang Qi 2013-05-14 14:19:47 +02:00 committed by The Qt Project
parent abaaaea041
commit 57acf1b46c
2 changed files with 66 additions and 13 deletions

View File

@ -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 += '"';

View File

@ -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]);
}
}