1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL21$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** In addition, as a special exception, Digia gives you certain additional
27 ** rights. These rights are described in the Digia Qt LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** $QT_END_LICENSE$
31 **
32 ****************************************************************************/
33
34 #include <QtTest>
35
36 #include "json/qjsonarray.h"
37 #include "json/qjsonobject.h"
38 #include "json/qjsonvalue.h"
39 #include "json/qjsondocument.h"
40 #include <limits>
41
42 #define INVALID_UNICODE "\xCE\xBA\xE1"
43 #define UNICODE_NON_CHARACTER "\xEF\xBF\xBF"
44 #define UNICODE_DJE "\320\202" // Character from the Serbian Cyrillic alphabet
45
46 class tst_QtJson: public QObject
47 {
48 Q_OBJECT
49 public:
50 tst_QtJson(QObject *parent = 0);
51
52 private Q_SLOTS:
53 void initTestCase();
54 void cleanupTestCase();
55 void init();
56 void cleanup();
57
58 void testValueSimple();
59 void testNumbers();
60 void testNumbers_2();
61 void testNumbers_3();
62
63 void testObjectSimple();
64 void testObjectSmallKeys();
65 void testArraySimple();
66 void testValueObject();
67 void testValueArray();
68 void testObjectNested();
69 void testArrayNested();
70 void testArrayNestedEmpty();
71 void testArrayComfortOperators();
72 void testObjectNestedEmpty();
73
74 void testValueRef();
75 void testObjectIteration();
76 void testArrayIteration();
77
78 void testObjectFind();
79
80 void testDocument();
81
82 void nullValues();
83 void nullArrays();
84 void nullObject();
85 void constNullObject();
86
87 void keySorting();
88
89 void undefinedValues();
90
91 void fromVariant();
92 void fromVariantMap();
93 void toVariantMap();
94 void toVariantList();
95
96 void toJson();
97 void toJsonSillyNumericValues();
98 void toJsonLargeNumericValues();
99 void fromJson();
100 void fromJsonErrors();
101 void fromBinary();
102 void toAndFromBinary_data();
103 void toAndFromBinary();
104 void parseNumbers();
105 void parseStrings();
106 void parseDuplicateKeys();
107 void testParser();
108
109 void compactArray();
110 void compactObject();
111
112 void validation();
113
114 void assignToDocument();
115
116 void testDuplicateKeys();
117 void testCompaction();
118 void testDebugStream();
119 void testCompactionError();
120
121 void parseUnicodeEscapes();
122
123 void assignObjects();
124 void assignArrays();
125
126 void testTrailingComma();
127 void testDetachBug();
128 void testJsonValueRefDefault();
129
130 void valueEquals();
131 void objectEquals_data();
132 void objectEquals();
133 void arrayEquals_data();
134 void arrayEquals();
135
136 void bom();
137 void nesting();
138
139 void longStrings();
140
141 void arrayInitializerList();
142 void objectInitializerList();
143
144 void unicodeKeys();
145 void garbageAtEnd();
146 };
147
tst_QtJson(QObject * parent)148 tst_QtJson::tst_QtJson(QObject *parent) : QObject(parent)
149 {
150 }
151
initTestCase()152 void tst_QtJson::initTestCase()
153 {
154 }
155
cleanupTestCase()156 void tst_QtJson::cleanupTestCase()
157 {
158 }
159
init()160 void tst_QtJson::init()
161 {
162 }
163
cleanup()164 void tst_QtJson::cleanup()
165 {
166 }
167
testValueSimple()168 void tst_QtJson::testValueSimple()
169 {
170 QJsonObject object;
171 object.insert("number", 999.);
172 QJsonArray array;
173 for (int i = 0; i < 10; ++i)
174 array.append((double)i);
175
176 QJsonValue value(true);
177 QCOMPARE(value.type(), QJsonValue::Bool);
178 QCOMPARE(value.toDouble(), 0.);
179 QCOMPARE(value.toString(), QString());
180 QCOMPARE(value.toBool(), true);
181 QCOMPARE(value.toObject(), QJsonObject());
182 QCOMPARE(value.toArray(), QJsonArray());
183 QCOMPARE(value.toDouble(99.), 99.);
184 QCOMPARE(value.toString(QString("test")), QString("test"));
185 QCOMPARE(value.toObject(object), object);
186 QCOMPARE(value.toArray(array), array);
187
188 value = 999.;
189 QCOMPARE(value.type(), QJsonValue::Double);
190 QCOMPARE(value.toDouble(), 999.);
191 QCOMPARE(value.toString(), QString());
192 QCOMPARE(value.toBool(), false);
193 QCOMPARE(value.toBool(true), true);
194 QCOMPARE(value.toObject(), QJsonObject());
195 QCOMPARE(value.toArray(), QJsonArray());
196
197 value = QLatin1String("test");
198 QCOMPARE(value.toDouble(), 0.);
199 QCOMPARE(value.toString(), QLatin1String("test"));
200 QCOMPARE(value.toBool(), false);
201 QCOMPARE(value.toObject(), QJsonObject());
202 QCOMPARE(value.toArray(), QJsonArray());
203 }
204
testNumbers()205 void tst_QtJson::testNumbers()
206 {
207 {
208 int numbers[] = {
209 0,
210 -1,
211 1,
212 (1<<26),
213 (1<<27),
214 (1<<28),
215 -(1<<26),
216 -(1<<27),
217 -(1<<28),
218 (1<<26) - 1,
219 (1<<27) - 1,
220 (1<<28) - 1,
221 -((1<<26) - 1),
222 -((1<<27) - 1),
223 -((1<<28) - 1)
224 };
225 int n = sizeof(numbers)/sizeof(int);
226
227 QJsonArray array;
228 for (int i = 0; i < n; ++i)
229 array.append((double)numbers[i]);
230
231 QByteArray serialized = QJsonDocument(array).toJson();
232 QJsonDocument json = QJsonDocument::fromJson(serialized);
233 QJsonArray array2 = json.array();
234
235 QCOMPARE(array.size(), array2.size());
236 for (int i = 0; i < array.size(); ++i) {
237 QCOMPARE(array.at(i).type(), QJsonValue::Double);
238 QCOMPARE(array.at(i).toDouble(), (double)numbers[i]);
239 QCOMPARE(array2.at(i).type(), QJsonValue::Double);
240 QCOMPARE(array2.at(i).toDouble(), (double)numbers[i]);
241 }
242 }
243
244 {
245 qint64 numbers[] = {
246 0,
247 -1,
248 1,
249 (1ll<<54),
250 (1ll<<55),
251 (1ll<<56),
252 -(1ll<<54),
253 -(1ll<<55),
254 -(1ll<<56),
255 (1ll<<54) - 1,
256 (1ll<<55) - 1,
257 (1ll<<56) - 1,
258 -((1ll<<54) - 1),
259 -((1ll<<55) - 1),
260 -((1ll<<56) - 1)
261 };
262 int n = sizeof(numbers)/sizeof(qint64);
263
264 QJsonArray array;
265 for (int i = 0; i < n; ++i)
266 array.append((double)numbers[i]);
267
268 QByteArray serialized = QJsonDocument(array).toJson();
269 QJsonDocument json = QJsonDocument::fromJson(serialized);
270 QJsonArray array2 = json.array();
271
272 QCOMPARE(array.size(), array2.size());
273 for (int i = 0; i < array.size(); ++i) {
274 QCOMPARE(array.at(i).type(), QJsonValue::Double);
275 QCOMPARE(array.at(i).toDouble(), (double)numbers[i]);
276 QCOMPARE(array2.at(i).type(), QJsonValue::Double);
277 QCOMPARE(array2.at(i).toDouble(), (double)numbers[i]);
278 }
279 }
280
281 {
282 double numbers[] = {
283 0,
284 -1,
285 1,
286 double(1ll<<54),
287 double(1ll<<55),
288 double(1ll<<56),
289 double(-(1ll<<54)),
290 double(-(1ll<<55)),
291 double(-(1ll<<56)),
292 double((1ll<<54) - 1),
293 double((1ll<<55) - 1),
294 double((1ll<<56) - 1),
295 double(-((1ll<<54) - 1)),
296 double(-((1ll<<55) - 1)),
297 double(-((1ll<<56) - 1)),
298 1.1,
299 0.1,
300 -0.1,
301 -1.1,
302 1e200,
303 -1e200
304 };
305 int n = sizeof(numbers)/sizeof(double);
306
307 QJsonArray array;
308 for (int i = 0; i < n; ++i)
309 array.append(numbers[i]);
310
311 QByteArray serialized = QJsonDocument(array).toJson();
312 QJsonDocument json = QJsonDocument::fromJson(serialized);
313 QJsonArray array2 = json.array();
314
315 QCOMPARE(array.size(), array2.size());
316 for (int i = 0; i < array.size(); ++i) {
317 QCOMPARE(array.at(i).type(), QJsonValue::Double);
318 QCOMPARE(array.at(i).toDouble(), numbers[i]);
319 QCOMPARE(array2.at(i).type(), QJsonValue::Double);
320 QCOMPARE(array2.at(i).toDouble(), numbers[i]);
321 }
322 }
323
324 }
325
testNumbers_2()326 void tst_QtJson::testNumbers_2()
327 {
328 // test cases from TC39 test suite for ECMAScript
329 // http://hg.ecmascript.org/tests/test262/file/d067d2f0ca30/test/suite/ch08/8.5/8.5.1.js
330
331 // Fill an array with 2 to the power of (0 ... -1075)
332 double value = 1;
333 double floatValues[1076], floatValues_1[1076];
334 QJsonObject jObject;
335 for (int power = 0; power <= 1075; power++) {
336 floatValues[power] = value;
337 jObject.insert(QString::number(power), QJsonValue(floatValues[power]));
338 // Use basic math operations for testing, which are required to support 'gradual underflow' rather
339 // than Math.pow etc..., which are defined as 'implementation dependent'.
340 value = value * 0.5;
341 }
342
343 QJsonDocument jDocument1(jObject);
344 QByteArray ba(jDocument1.toJson());
345
346 QJsonDocument jDocument2(QJsonDocument::fromJson(ba));
347 for (int power = 0; power <= 1075; power++) {
348 floatValues_1[power] = jDocument2.object().value(QString::number(power)).toDouble();
349 #ifdef Q_OS_QNX
350 if (power >= 970)
351 QEXPECT_FAIL("", "See QTBUG-37066", Abort);
352 #endif
353 QVERIFY2(floatValues[power] == floatValues_1[power], QString("floatValues[%1] != floatValues_1[%1]").arg(power).toLatin1());
354 }
355
356 // The last value is below min denorm and should round to 0, everything else should contain a value
357 QVERIFY2(floatValues_1[1075] == 0, "Value after min denorm should round to 0");
358
359 // Validate the last actual value is min denorm
360 QVERIFY2(floatValues_1[1074] == 4.9406564584124654417656879286822e-324, QString("Min denorm value is incorrect: %1").arg(floatValues_1[1074]).toLatin1());
361
362 // Validate that every value is half the value before it up to 1
363 for (int index = 1074; index > 0; index--) {
364 QVERIFY2(floatValues_1[index] != 0, QString("2**- %1 should not be 0").arg(index).toLatin1());
365
366 QVERIFY2(floatValues_1[index - 1] == (floatValues_1[index] * 2), QString("Value should be double adjacent value at index %1").arg(index).toLatin1());
367 }
368 }
369
testNumbers_3()370 void tst_QtJson::testNumbers_3()
371 {
372 // test case from QTBUG-31926
373 double d1 = 1.123451234512345;
374 double d2 = 1.123451234512346;
375
376 QJsonObject jObject;
377 jObject.insert("d1", QJsonValue(d1));
378 jObject.insert("d2", QJsonValue(d2));
379 QJsonDocument jDocument1(jObject);
380 QByteArray ba(jDocument1.toJson());
381
382 QJsonDocument jDocument2(QJsonDocument::fromJson(ba));
383
384 double d1_1(jDocument2.object().value("d1").toDouble());
385 double d2_1(jDocument2.object().value("d2").toDouble());
386 QVERIFY(d1_1 != d2_1);
387 }
388
testObjectSimple()389 void tst_QtJson::testObjectSimple()
390 {
391 QJsonObject object;
392 object.insert("number", 999.);
393 QCOMPARE(object.value("number").type(), QJsonValue::Double);
394 QCOMPARE(object.value("number").toDouble(), 999.);
395 object.insert("string", QString::fromLatin1("test"));
396 QCOMPARE(object.value("string").type(), QJsonValue::String);
397 QCOMPARE(object.value("string").toString(), QString("test"));
398 object.insert("boolean", true);
399 QCOMPARE(object.value("boolean").toBool(), true);
400
401 QStringList keys = object.keys();
402 QVERIFY2(keys.contains("number"), "key number not found");
403 QVERIFY2(keys.contains("string"), "key string not found");
404 QVERIFY2(keys.contains("boolean"), "key boolean not found");
405
406 // if we put a JsonValue into the JsonObject and retrieve
407 // it, it should be identical.
408 QJsonValue value(QLatin1String("foo"));
409 object.insert("value", value);
410 QCOMPARE(object.value("value"), value);
411
412 int size = object.size();
413 object.remove("boolean");
414 QCOMPARE(object.size(), size - 1);
415 QVERIFY2(!object.contains("boolean"), "key boolean should have been removed");
416
417 QJsonValue taken = object.take("value");
418 QCOMPARE(taken, value);
419 QVERIFY2(!object.contains("value"), "key value should have been removed");
420
421 QString before = object.value("string").toString();
422 object.insert("string", QString::fromLatin1("foo"));
423 QVERIFY2(object.value("string").toString() != before, "value should have been updated");
424
425 size = object.size();
426 QJsonObject subobject;
427 subobject.insert("number", 42);
428 subobject.insert(QLatin1String("string"), QLatin1String("foobar"));
429 object.insert("subobject", subobject);
430 QCOMPARE(object.size(), size+1);
431 QJsonValue subvalue = object.take(QLatin1String("subobject"));
432 QCOMPARE(object.size(), size);
433 QCOMPARE(subvalue.toObject(), subobject);
434 // make object detach by modifying it many times
435 for (int i = 0; i < 64; ++i)
436 object.insert(QLatin1String("string"), QLatin1String("bar"));
437 QCOMPARE(object.size(), size);
438 QCOMPARE(subvalue.toObject(), subobject);
439 }
440
testObjectSmallKeys()441 void tst_QtJson::testObjectSmallKeys()
442 {
443 QJsonObject data1;
444 data1.insert(QLatin1String("1"), 123);
445 QVERIFY(data1.contains(QLatin1String("1")));
446 QCOMPARE(data1.value(QLatin1String("1")).toDouble(), (double)123);
447 data1.insert(QLatin1String("12"), 133);
448 QCOMPARE(data1.value(QLatin1String("12")).toDouble(), (double)133);
449 QVERIFY(data1.contains(QLatin1String("12")));
450 data1.insert(QLatin1String("123"), 323);
451 QCOMPARE(data1.value(QLatin1String("12")).toDouble(), (double)133);
452 QVERIFY(data1.contains(QLatin1String("123")));
453 QCOMPARE(data1.value(QLatin1String("123")).type(), QJsonValue::Double);
454 QCOMPARE(data1.value(QLatin1String("123")).toDouble(), (double)323);
455 }
456
testArraySimple()457 void tst_QtJson::testArraySimple()
458 {
459 QJsonArray array;
460 array.append(999.);
461 array.append(QString::fromLatin1("test"));
462 array.append(true);
463
464 QJsonValue val = array.at(0);
465 QCOMPARE(array.at(0).toDouble(), 999.);
466 QCOMPARE(array.at(1).toString(), QString("test"));
467 QCOMPARE(array.at(2).toBool(), true);
468 QCOMPARE(array.size(), 3);
469
470 // if we put a JsonValue into the JsonArray and retrieve
471 // it, it should be identical.
472 QJsonValue value(QLatin1String("foo"));
473 array.append(value);
474 QCOMPARE(array.at(3), value);
475
476 int size = array.size();
477 array.removeAt(2);
478 --size;
479 QCOMPARE(array.size(), size);
480
481 QJsonValue taken = array.takeAt(0);
482 --size;
483 QCOMPARE(taken.toDouble(), 999.);
484 QCOMPARE(array.size(), size);
485
486 // check whether null values work
487 array.append(QJsonValue());
488 ++size;
489 QCOMPARE(array.size(), size);
490 QCOMPARE(array.last().type(), QJsonValue::Null);
491 QCOMPARE(array.last(), QJsonValue());
492
493 QCOMPARE(array.first().type(), QJsonValue::String);
494 QCOMPARE(array.first(), QJsonValue(QLatin1String("test")));
495
496 array.prepend(false);
497 QCOMPARE(array.first().type(), QJsonValue::Bool);
498 QCOMPARE(array.first(), QJsonValue(false));
499
500 QCOMPARE(array.at(-1), QJsonValue(QJsonValue::Undefined));
501 QCOMPARE(array.at(array.size()), QJsonValue(QJsonValue::Undefined));
502
503 array.replace(0, -555.);
504 QCOMPARE(array.first().type(), QJsonValue::Double);
505 QCOMPARE(array.first(), QJsonValue(-555.));
506 QCOMPARE(array.at(1).type(), QJsonValue::String);
507 QCOMPARE(array.at(1), QJsonValue(QLatin1String("test")));
508 }
509
testValueObject()510 void tst_QtJson::testValueObject()
511 {
512 QJsonObject object;
513 object.insert("number", 999.);
514 object.insert("string", QLatin1String("test"));
515 object.insert("boolean", true);
516
517 QJsonValue value(object);
518
519 // if we don't modify the original JsonObject, toObject()
520 // on the JsonValue should return the same object (non-detached).
521 QCOMPARE(value.toObject(), object);
522
523 // if we modify the original object, it should detach
524 object.insert("test", QJsonValue(QLatin1String("test")));
525 QVERIFY2(value.toObject() != object, "object should have detached");
526 }
527
testValueArray()528 void tst_QtJson::testValueArray()
529 {
530 QJsonArray array;
531 array.append(999.);
532 array.append(QLatin1String("test"));
533 array.append(true);
534
535 QJsonValue value(array);
536
537 // if we don't modify the original JsonArray, toArray()
538 // on the JsonValue should return the same object (non-detached).
539 QCOMPARE(value.toArray(), array);
540
541 // if we modify the original array, it should detach
542 array.append(QLatin1String("test"));
543 QVERIFY2(value.toArray() != array, "array should have detached");
544 }
545
testObjectNested()546 void tst_QtJson::testObjectNested()
547 {
548 QJsonObject inner, outer;
549 inner.insert("number", 999.);
550 outer.insert("nested", inner);
551
552 // if we don't modify the original JsonObject, value()
553 // should return the same object (non-detached).
554 QJsonObject value = outer.value("nested").toObject();
555 QCOMPARE(value, inner);
556 QCOMPARE(value.value("number").toDouble(), 999.);
557
558 // if we modify the original object, it should detach and not
559 // affect the nested object
560 inner.insert("number", 555.);
561 value = outer.value("nested").toObject();
562 QVERIFY2(inner.value("number").toDouble() != value.value("number").toDouble(),
563 "object should have detached");
564
565 // array in object
566 QJsonArray array;
567 array.append(123.);
568 array.append(456.);
569 outer.insert("array", array);
570 QCOMPARE(outer.value("array").toArray(), array);
571 QCOMPARE(outer.value("array").toArray().at(1).toDouble(), 456.);
572
573 // two deep objects
574 QJsonObject twoDeep;
575 twoDeep.insert("boolean", true);
576 inner.insert("nested", twoDeep);
577 outer.insert("nested", inner);
578 QCOMPARE(outer.value("nested").toObject().value("nested").toObject(), twoDeep);
579 QCOMPARE(outer.value("nested").toObject().value("nested").toObject().value("boolean").toBool(),
580 true);
581 }
582
testArrayNested()583 void tst_QtJson::testArrayNested()
584 {
585 QJsonArray inner, outer;
586 inner.append(999.);
587 outer.append(inner);
588
589 // if we don't modify the original JsonArray, value()
590 // should return the same array (non-detached).
591 QJsonArray value = outer.at(0).toArray();
592 QCOMPARE(value, inner);
593 QCOMPARE(value.at(0).toDouble(), 999.);
594
595 // if we modify the original array, it should detach and not
596 // affect the nested array
597 inner.append(555.);
598 value = outer.at(0).toArray();
599 QVERIFY2(inner.size() != value.size(), "array should have detached");
600
601 // objects in arrays
602 QJsonObject object;
603 object.insert("boolean", true);
604 outer.append(object);
605 QCOMPARE(outer.last().toObject(), object);
606 QCOMPARE(outer.last().toObject().value("boolean").toBool(), true);
607
608 // two deep arrays
609 QJsonArray twoDeep;
610 twoDeep.append(QJsonValue(QString::fromLatin1("nested")));
611 inner.append(twoDeep);
612 outer.append(inner);
613 QCOMPARE(outer.last().toArray().last().toArray(), twoDeep);
614 QCOMPARE(outer.last().toArray().last().toArray().at(0).toString(), QString("nested"));
615 }
616
testArrayNestedEmpty()617 void tst_QtJson::testArrayNestedEmpty()
618 {
619 QJsonObject object;
620 QJsonArray inner;
621 object.insert("inner", inner);
622 QJsonValue val = object.value("inner");
623 QJsonArray value = object.value("inner").toArray();
624 QCOMPARE(value.size(), 0);
625 QCOMPARE(value, inner);
626 QCOMPARE(value.size(), 0);
627 object.insert("count", 0.);
628 QCOMPARE(object.value("inner").toArray().size(), 0);
629 QVERIFY(object.value("inner").toArray().isEmpty());
630 QJsonDocument(object).toBinaryData();
631 QCOMPARE(object.value("inner").toArray().size(), 0);
632 }
633
testObjectNestedEmpty()634 void tst_QtJson::testObjectNestedEmpty()
635 {
636 QJsonObject object;
637 QJsonObject inner;
638 QJsonObject inner2;
639 object.insert("inner", inner);
640 object.insert("inner2", inner2);
641 QJsonObject value = object.value("inner").toObject();
642 QCOMPARE(value.size(), 0);
643 QCOMPARE(value, inner);
644 QCOMPARE(value.size(), 0);
645 object.insert("count", 0.);
646 QCOMPARE(object.value("inner").toObject().size(), 0);
647 QCOMPARE(object.value("inner").type(), QJsonValue::Object);
648 QJsonDocument(object).toBinaryData();
649 QVERIFY(object.value("inner").toObject().isEmpty());
650 QVERIFY(object.value("inner2").toObject().isEmpty());
651 QJsonDocument doc = QJsonDocument::fromBinaryData(QJsonDocument(object).toBinaryData());
652 QVERIFY(!doc.isNull());
653 QJsonObject reconstituted(doc.object());
654 QCOMPARE(reconstituted.value("inner").toObject().size(), 0);
655 QCOMPARE(reconstituted.value("inner").type(), QJsonValue::Object);
656 QCOMPARE(reconstituted.value("inner2").type(), QJsonValue::Object);
657 }
658
testArrayComfortOperators()659 void tst_QtJson::testArrayComfortOperators()
660 {
661 QJsonArray first;
662 first.append(123.);
663 first.append(QLatin1String("foo"));
664
665 QJsonArray second = QJsonArray() << 123. << QLatin1String("foo");
666 QCOMPARE(first, second);
667
668 first = first + QLatin1String("bar");
669 second += QLatin1String("bar");
670 QCOMPARE(first, second);
671 }
672
testValueRef()673 void tst_QtJson::testValueRef()
674 {
675 QJsonArray array;
676 array.append(1.);
677 array.append(2.);
678 array.append(3.);
679 array.append(4);
680 array.append(4.1);
681 array[1] = false;
682
683 QCOMPARE(array.size(), 5);
684 QCOMPARE(array.at(0).toDouble(), 1.);
685 QCOMPARE(array.at(2).toDouble(), 3.);
686 #if QT_VERSION >= 0x050200
687 QCOMPARE(array.at(3).toInt(), 4);
688 QCOMPARE(array.at(4).toInt(), 0);
689 #endif
690 QCOMPARE(array.at(1).type(), QJsonValue::Bool);
691 QCOMPARE(array.at(1).toBool(), false);
692
693 QJsonObject object;
694 object[QLatin1String("key")] = true;
695 QCOMPARE(object.size(), 1);
696 object.insert(QLatin1String("null"), QJsonValue());
697 QCOMPARE(object.value(QLatin1String("null")), QJsonValue());
698 object[QLatin1String("null")] = 100.;
699 QCOMPARE(object.value(QLatin1String("null")).type(), QJsonValue::Double);
700 QJsonValue val = object[QLatin1String("null")];
701 QCOMPARE(val.toDouble(), 100.);
702 QCOMPARE(object.size(), 2);
703
704 array[1] = array[2] = object[QLatin1String("key")] = 42;
705 QCOMPARE(array[1], array[2]);
706 QCOMPARE(array[2], object[QLatin1String("key")]);
707 QCOMPARE(object.value(QLatin1String("key")), QJsonValue(42));
708 }
709
testObjectIteration()710 void tst_QtJson::testObjectIteration()
711 {
712 QJsonObject object;
713
714 for (QJsonObject::iterator it = object.begin(); it != object.end(); ++it)
715 QVERIFY(false);
716
717 const QString property = "kkk";
718 object.insert(property, 11);
719 object.take(property);
720 for (QJsonObject::iterator it = object.begin(); it != object.end(); ++it)
721 QVERIFY(false);
722
723 for (int i = 0; i < 10; ++i)
724 object[QString::number(i)] = (double)i;
725
726 QCOMPARE(object.size(), 10);
727
728 QCOMPARE(object.begin()->toDouble(), object.constBegin()->toDouble());
729
730 for (QJsonObject::iterator it = object.begin(); it != object.end(); ++it) {
731 QJsonValue value = it.value();
732 QCOMPARE((double)it.key().toInt(), value.toDouble());
733 }
734
735 {
736 QJsonObject object2 = object;
737 QVERIFY(object == object2);
738
739 QJsonValue val = *object2.begin();
740 object2.erase(object2.begin());
741 QCOMPARE(object.size(), 10);
742 QCOMPARE(object2.size(), 9);
743
744 for (QJsonObject::const_iterator it = object2.constBegin(); it != object2.constEnd(); ++it) {
745 QJsonValue value = it.value();
746 QVERIFY(it.value() != val);
747 QCOMPARE((double)it.key().toInt(), value.toDouble());
748 }
749 }
750
751 {
752 QJsonObject object2 = object;
753 QVERIFY(object == object2);
754
755 QJsonObject::iterator it = object2.find(QString::number(5));
756 object2.erase(it);
757 QCOMPARE(object.size(), 10);
758 QCOMPARE(object2.size(), 9);
759 }
760
761 {
762 QJsonObject::Iterator it = object.begin();
763 it += 5;
764 QCOMPARE(QJsonValue(it.value()).toDouble(), 5.);
765 it -= 3;
766 QCOMPARE(QJsonValue(it.value()).toDouble(), 2.);
767 QJsonObject::Iterator it2 = it + 5;
768 QCOMPARE(QJsonValue(it2.value()).toDouble(), 7.);
769 it2 = it - 1;
770 QCOMPARE(QJsonValue(it2.value()).toDouble(), 1.);
771 }
772
773 {
774 QJsonObject::ConstIterator it = object.constBegin();
775 it += 5;
776 QCOMPARE(QJsonValue(it.value()).toDouble(), 5.);
777 it -= 3;
778 QCOMPARE(QJsonValue(it.value()).toDouble(), 2.);
779 QJsonObject::ConstIterator it2 = it + 5;
780 QCOMPARE(QJsonValue(it2.value()).toDouble(), 7.);
781 it2 = it - 1;
782 QCOMPARE(QJsonValue(it2.value()).toDouble(), 1.);
783 }
784
785 QJsonObject::Iterator it = object.begin();
786 while (!object.isEmpty())
787 it = object.erase(it);
788 QCOMPARE(object.size() , 0);
789 QVERIFY(it == object.end());
790 }
791
testArrayIteration()792 void tst_QtJson::testArrayIteration()
793 {
794 QJsonArray array;
795 for (int i = 0; i < 10; ++i)
796 array.append(i);
797
798 QCOMPARE(array.size(), 10);
799
800 int i = 0;
801 for (QJsonArray::iterator it = array.begin(); it != array.end(); ++it, ++i) {
802 QJsonValue value = (*it);
803 QCOMPARE((double)i, value.toDouble());
804 }
805
806 QCOMPARE(array.begin()->toDouble(), array.constBegin()->toDouble());
807
808 {
809 QJsonArray array2 = array;
810 QVERIFY(array == array2);
811
812 QJsonValue val = *array2.begin();
813 array2.erase(array2.begin());
814 QCOMPARE(array.size(), 10);
815 QCOMPARE(array2.size(), 9);
816
817 i = 1;
818 for (QJsonArray::const_iterator it = array2.constBegin(); it != array2.constEnd(); ++it, ++i) {
819 QJsonValue value = (*it);
820 QCOMPARE((double)i, value.toDouble());
821 }
822 }
823
824 {
825 QJsonArray::Iterator it = array.begin();
826 it += 5;
827 QCOMPARE(QJsonValue((*it)).toDouble(), 5.);
828 it -= 3;
829 QCOMPARE(QJsonValue((*it)).toDouble(), 2.);
830 QJsonArray::Iterator it2 = it + 5;
831 QCOMPARE(QJsonValue(*it2).toDouble(), 7.);
832 it2 = it - 1;
833 QCOMPARE(QJsonValue(*it2).toDouble(), 1.);
834 }
835
836 {
837 QJsonArray::ConstIterator it = array.constBegin();
838 it += 5;
839 QCOMPARE(QJsonValue((*it)).toDouble(), 5.);
840 it -= 3;
841 QCOMPARE(QJsonValue((*it)).toDouble(), 2.);
842 QJsonArray::ConstIterator it2 = it + 5;
843 QCOMPARE(QJsonValue(*it2).toDouble(), 7.);
844 it2 = it - 1;
845 QCOMPARE(QJsonValue(*it2).toDouble(), 1.);
846 }
847
848 QJsonArray::Iterator it = array.begin();
849 while (!array.isEmpty())
850 it = array.erase(it);
851 QCOMPARE(array.size() , 0);
852 QVERIFY(it == array.end());
853 }
854
testObjectFind()855 void tst_QtJson::testObjectFind()
856 {
857 QJsonObject object;
858 for (int i = 0; i < 10; ++i)
859 object[QString::number(i)] = i;
860
861 QCOMPARE(object.size(), 10);
862
863 QJsonObject::iterator it = object.find(QLatin1String("1"));
864 QCOMPARE((*it).toDouble(), 1.);
865 it = object.find(QLatin1String("11"));
866 QVERIFY((*it).type() == QJsonValue::Undefined);
867 QVERIFY(it == object.end());
868
869 QJsonObject::const_iterator cit = object.constFind(QLatin1String("1"));
870 QCOMPARE((*cit).toDouble(), 1.);
871 cit = object.constFind(QLatin1String("11"));
872 QVERIFY((*it).type() == QJsonValue::Undefined);
873 QVERIFY(it == object.end());
874 }
875
testDocument()876 void tst_QtJson::testDocument()
877 {
878 QJsonDocument doc;
879 QCOMPARE(doc.isEmpty(), true);
880 QCOMPARE(doc.isArray(), false);
881 QCOMPARE(doc.isObject(), false);
882
883 QJsonObject object;
884 doc.setObject(object);
885 QCOMPARE(doc.isEmpty(), false);
886 QCOMPARE(doc.isArray(), false);
887 QCOMPARE(doc.isObject(), true);
888
889 object.insert(QLatin1String("Key"), QLatin1String("Value"));
890 doc.setObject(object);
891 QCOMPARE(doc.isEmpty(), false);
892 QCOMPARE(doc.isArray(), false);
893 QCOMPARE(doc.isObject(), true);
894 QVERIFY(doc.object() == object);
895 QVERIFY(doc.array() == QJsonArray());
896
897 doc = QJsonDocument();
898 QCOMPARE(doc.isEmpty(), true);
899 QCOMPARE(doc.isArray(), false);
900 QCOMPARE(doc.isObject(), false);
901
902 QJsonArray array;
903 doc.setArray(array);
904 QCOMPARE(doc.isEmpty(), false);
905 QCOMPARE(doc.isArray(), true);
906 QCOMPARE(doc.isObject(), false);
907
908 array.append(QLatin1String("Value"));
909 doc.setArray(array);
910 QCOMPARE(doc.isEmpty(), false);
911 QCOMPARE(doc.isArray(), true);
912 QCOMPARE(doc.isObject(), false);
913 QVERIFY(doc.array() == array);
914 QVERIFY(doc.object() == QJsonObject());
915
916 QJsonObject outer;
917 outer.insert(QLatin1String("outerKey"), 22);
918 QJsonObject inner;
919 inner.insert(QLatin1String("innerKey"), 42);
920 outer.insert(QLatin1String("innter"), inner);
921 QJsonArray innerArray;
922 innerArray.append(23);
923 outer.insert(QLatin1String("innterArray"), innerArray);
924
925 QJsonDocument doc2(outer.value(QLatin1String("innter")).toObject());
926 QVERIFY(doc2.object().contains(QLatin1String("innerKey")));
927 QCOMPARE(doc2.object().value(QLatin1String("innerKey")), QJsonValue(42));
928
929 QJsonDocument doc3;
930 doc3.setObject(outer.value(QLatin1String("innter")).toObject());
931 QCOMPARE(doc3.isArray(), false);
932 QCOMPARE(doc3.isObject(), true);
933 QVERIFY(doc3.object().contains(QLatin1String("innerKey")));
934 QCOMPARE(doc3.object().value(QLatin1String("innerKey")), QJsonValue(42));
935
936 QJsonDocument doc4(outer.value(QLatin1String("innterArray")).toArray());
937 QCOMPARE(doc4.isArray(), true);
938 QCOMPARE(doc4.isObject(), false);
939 QCOMPARE(doc4.array().size(), 1);
940 QCOMPARE(doc4.array().at(0), QJsonValue(23));
941
942 QJsonDocument doc5;
943 doc5.setArray(outer.value(QLatin1String("innterArray")).toArray());
944 QCOMPARE(doc5.isArray(), true);
945 QCOMPARE(doc5.isObject(), false);
946 QCOMPARE(doc5.array().size(), 1);
947 QCOMPARE(doc5.array().at(0), QJsonValue(23));
948 }
949
nullValues()950 void tst_QtJson::nullValues()
951 {
952 QJsonArray array;
953 array.append(QJsonValue());
954
955 QCOMPARE(array.size(), 1);
956 QCOMPARE(array.at(0), QJsonValue());
957
958 QJsonObject object;
959 object.insert(QString("key"), QJsonValue());
960 QCOMPARE(object.contains("key"), true);
961 QCOMPARE(object.size(), 1);
962 QCOMPARE(object.value("key"), QJsonValue());
963 }
964
nullArrays()965 void tst_QtJson::nullArrays()
966 {
967 QJsonArray nullArray;
968 QJsonArray nonNull;
969 nonNull.append(QLatin1String("bar"));
970
971 QCOMPARE(nullArray, QJsonArray());
972 QVERIFY(nullArray != nonNull);
973 QVERIFY(nonNull != nullArray);
974
975 QCOMPARE(nullArray.size(), 0);
976 QCOMPARE(nullArray.takeAt(0), QJsonValue(QJsonValue::Undefined));
977 QCOMPARE(nullArray.first(), QJsonValue(QJsonValue::Undefined));
978 QCOMPARE(nullArray.last(), QJsonValue(QJsonValue::Undefined));
979 nullArray.removeAt(0);
980 nullArray.removeAt(-1);
981
982 nullArray.append(QString("bar"));
983 nullArray.removeAt(0);
984
985 QCOMPARE(nullArray.size(), 0);
986 QCOMPARE(nullArray.takeAt(0), QJsonValue(QJsonValue::Undefined));
987 QCOMPARE(nullArray.first(), QJsonValue(QJsonValue::Undefined));
988 QCOMPARE(nullArray.last(), QJsonValue(QJsonValue::Undefined));
989 nullArray.removeAt(0);
990 nullArray.removeAt(-1);
991 }
992
nullObject()993 void tst_QtJson::nullObject()
994 {
995 QJsonObject nullObject;
996 QJsonObject nonNull;
997 nonNull.insert(QLatin1String("foo"), QLatin1String("bar"));
998
999 QCOMPARE(nullObject, QJsonObject());
1000 QVERIFY(nullObject != nonNull);
1001 QVERIFY(nonNull != nullObject);
1002
1003 QCOMPARE(nullObject.size(), 0);
1004 QCOMPARE(nullObject.keys(), QStringList());
1005 nullObject.remove("foo");
1006 QCOMPARE(nullObject, QJsonObject());
1007 QCOMPARE(nullObject.take("foo"), QJsonValue(QJsonValue::Undefined));
1008 QCOMPARE(nullObject.contains("foo"), false);
1009
1010 nullObject.insert("foo", QString("bar"));
1011 nullObject.remove("foo");
1012
1013 QCOMPARE(nullObject.size(), 0);
1014 QCOMPARE(nullObject.keys(), QStringList());
1015 nullObject.remove("foo");
1016 QCOMPARE(nullObject, QJsonObject());
1017 QCOMPARE(nullObject.take("foo"), QJsonValue(QJsonValue::Undefined));
1018 QCOMPARE(nullObject.contains("foo"), false);
1019 }
1020
constNullObject()1021 void tst_QtJson::constNullObject()
1022 {
1023 const QJsonObject nullObject;
1024 QJsonObject nonNull;
1025 nonNull.insert(QLatin1String("foo"), QLatin1String("bar"));
1026
1027 QCOMPARE(nullObject, QJsonObject());
1028 QVERIFY(nullObject != nonNull);
1029 QVERIFY(nonNull != nullObject);
1030
1031 QCOMPARE(nullObject.size(), 0);
1032 QCOMPARE(nullObject.keys(), QStringList());
1033 QCOMPARE(nullObject, QJsonObject());
1034 QCOMPARE(nullObject.contains("foo"), false);
1035 QCOMPARE(nullObject["foo"], QJsonValue(QJsonValue::Undefined));
1036 }
1037
keySorting()1038 void tst_QtJson::keySorting()
1039 {
1040 const char *json = "{ \"B\": true, \"A\": false }";
1041 QJsonDocument doc = QJsonDocument::fromJson(json);
1042
1043 QCOMPARE(doc.isObject(), true);
1044
1045 QJsonObject o = doc.object();
1046 QCOMPARE(o.size(), 2);
1047 QJsonObject::const_iterator it = o.constBegin();
1048 QCOMPARE(it.key(), QLatin1String("A"));
1049 ++it;
1050 QCOMPARE(it.key(), QLatin1String("B"));
1051 }
1052
undefinedValues()1053 void tst_QtJson::undefinedValues()
1054 {
1055 QJsonObject object;
1056 object.insert("Key", QJsonValue(QJsonValue::Undefined));
1057 QCOMPARE(object.size(), 0);
1058
1059 object.insert("Key", QLatin1String("Value"));
1060 QCOMPARE(object.size(), 1);
1061 QCOMPARE(object.value("Key").type(), QJsonValue::String);
1062 QCOMPARE(object.value("foo").type(), QJsonValue::Undefined);
1063 object.insert("Key", QJsonValue(QJsonValue::Undefined));
1064 QCOMPARE(object.size(), 0);
1065 QCOMPARE(object.value("Key").type(), QJsonValue::Undefined);
1066
1067 QJsonArray array;
1068 array.append(QJsonValue(QJsonValue::Undefined));
1069 QCOMPARE(array.size(), 1);
1070 QCOMPARE(array.at(0).type(), QJsonValue::Null);
1071
1072 QCOMPARE(array.at(1).type(), QJsonValue::Undefined);
1073 QCOMPARE(array.at(-1).type(), QJsonValue::Undefined);
1074 }
1075
fromVariant()1076 void tst_QtJson::fromVariant()
1077 {
1078 bool boolValue = true;
1079 int intValue = -1;
1080 uint uintValue = 1;
1081 long long longlongValue = -2;
1082 unsigned long long ulonglongValue = 2;
1083 float floatValue = 3.3f;
1084 double doubleValue = 4.4;
1085 QString stringValue("str");
1086
1087 QStringList stringList;
1088 stringList.append(stringValue);
1089 stringList.append("str2");
1090 QJsonArray jsonArray_string;
1091 jsonArray_string.append(stringValue);
1092 jsonArray_string.append("str2");
1093
1094 QVariantList variantList;
1095 variantList.append(boolValue);
1096 variantList.append(floatValue);
1097 variantList.append(doubleValue);
1098 variantList.append(stringValue);
1099 variantList.append(stringList);
1100 variantList.append(QVariant());
1101 QJsonArray jsonArray_variant;
1102 jsonArray_variant.append(boolValue);
1103 jsonArray_variant.append(floatValue);
1104 jsonArray_variant.append(doubleValue);
1105 jsonArray_variant.append(stringValue);
1106 jsonArray_variant.append(jsonArray_string);
1107 jsonArray_variant.append(QJsonValue());
1108
1109 QVariantMap variantMap;
1110 variantMap["bool"] = boolValue;
1111 variantMap["float"] = floatValue;
1112 variantMap["string"] = stringValue;
1113 variantMap["array"] = variantList;
1114 QJsonObject jsonObject;
1115 jsonObject["bool"] = boolValue;
1116 jsonObject["float"] = floatValue;
1117 jsonObject["string"] = stringValue;
1118 jsonObject["array"] = jsonArray_variant;
1119
1120 QCOMPARE(QJsonValue::fromVariant(QVariant(boolValue)), QJsonValue(boolValue));
1121 QCOMPARE(QJsonValue::fromVariant(QVariant(intValue)), QJsonValue(intValue));
1122 QCOMPARE(QJsonValue::fromVariant(QVariant(uintValue)), QJsonValue(static_cast<double>(uintValue)));
1123 QCOMPARE(QJsonValue::fromVariant(QVariant(longlongValue)), QJsonValue(longlongValue));
1124 QCOMPARE(QJsonValue::fromVariant(QVariant(ulonglongValue)), QJsonValue(static_cast<double>(ulonglongValue)));
1125 QCOMPARE(QJsonValue::fromVariant(QVariant(floatValue)), QJsonValue(static_cast<double>(floatValue)));
1126 QCOMPARE(QJsonValue::fromVariant(QVariant(doubleValue)), QJsonValue(doubleValue));
1127 QCOMPARE(QJsonValue::fromVariant(QVariant(stringValue)), QJsonValue(stringValue));
1128 QCOMPARE(QJsonValue::fromVariant(QVariant(stringList)), QJsonValue(jsonArray_string));
1129 QCOMPARE(QJsonValue::fromVariant(QVariant(variantList)), QJsonValue(jsonArray_variant));
1130 QCOMPARE(QJsonValue::fromVariant(QVariant(variantMap)), QJsonValue(jsonObject));
1131 }
1132
fromVariantMap()1133 void tst_QtJson::fromVariantMap()
1134 {
1135 QVariantMap map;
1136 map.insert(QLatin1String("key1"), QLatin1String("value1"));
1137 map.insert(QLatin1String("key2"), QLatin1String("value2"));
1138 QJsonObject object = QJsonObject::fromVariantMap(map);
1139 QCOMPARE(object.size(), 2);
1140 QCOMPARE(object.value(QLatin1String("key1")), QJsonValue(QLatin1String("value1")));
1141 QCOMPARE(object.value(QLatin1String("key2")), QJsonValue(QLatin1String("value2")));
1142
1143 QVariantList list;
1144 list.append(true);
1145 list.append(QVariant());
1146 list.append(999.);
1147 list.append(QLatin1String("foo"));
1148 map.insert("list", list);
1149 object = QJsonObject::fromVariantMap(map);
1150 QCOMPARE(object.size(), 3);
1151 QCOMPARE(object.value(QLatin1String("key1")), QJsonValue(QLatin1String("value1")));
1152 QCOMPARE(object.value(QLatin1String("key2")), QJsonValue(QLatin1String("value2")));
1153 QCOMPARE(object.value(QLatin1String("list")).type(), QJsonValue::Array);
1154 QJsonArray array = object.value(QLatin1String("list")).toArray();
1155 QCOMPARE(array.size(), 4);
1156 QCOMPARE(array.at(0).type(), QJsonValue::Bool);
1157 QCOMPARE(array.at(0).toBool(), true);
1158 QCOMPARE(array.at(1).type(), QJsonValue::Null);
1159 QCOMPARE(array.at(2).type(), QJsonValue::Double);
1160 QCOMPARE(array.at(2).toDouble(), 999.);
1161 QCOMPARE(array.at(3).type(), QJsonValue::String);
1162 QCOMPARE(array.at(3).toString(), QLatin1String("foo"));
1163 }
1164
toVariantMap()1165 void tst_QtJson::toVariantMap()
1166 {
1167 QCOMPARE(QMetaType::Type(QJsonValue(QJsonObject()).toVariant().type()), QMetaType::QVariantMap); // QTBUG-32524
1168
1169 QJsonObject object;
1170 QVariantMap map = object.toVariantMap();
1171 QVERIFY(map.isEmpty());
1172
1173 object.insert("Key", QString("Value"));
1174 object.insert("null", QJsonValue());
1175 QJsonArray array;
1176 array.append(true);
1177 array.append(999.);
1178 array.append(QLatin1String("string"));
1179 array.append(QJsonValue());
1180 object.insert("Array", array);
1181
1182 map = object.toVariantMap();
1183
1184 QCOMPARE(map.size(), 3);
1185 QCOMPARE(map.value("Key"), QVariant(QString("Value")));
1186 QCOMPARE(map.value("null"), QVariant());
1187 QCOMPARE(map.value("Array").type(), QVariant::List);
1188 QVariantList list = map.value("Array").toList();
1189 QCOMPARE(list.size(), 4);
1190 QCOMPARE(list.at(0), QVariant(true));
1191 QCOMPARE(list.at(1), QVariant(999.));
1192 QCOMPARE(list.at(2), QVariant(QLatin1String("string")));
1193 QCOMPARE(list.at(3), QVariant());
1194 }
1195
toVariantList()1196 void tst_QtJson::toVariantList()
1197 {
1198 QCOMPARE(QMetaType::Type(QJsonValue(QJsonArray()).toVariant().type()), QMetaType::QVariantList); // QTBUG-32524
1199
1200 QJsonArray array;
1201 QVariantList list = array.toVariantList();
1202 QVERIFY(list.isEmpty());
1203
1204 array.append(QString("Value"));
1205 array.append(QJsonValue());
1206 QJsonArray inner;
1207 inner.append(true);
1208 inner.append(999.);
1209 inner.append(QLatin1String("string"));
1210 inner.append(QJsonValue());
1211 array.append(inner);
1212
1213 list = array.toVariantList();
1214
1215 QCOMPARE(list.size(), 3);
1216 QCOMPARE(list[0], QVariant(QString("Value")));
1217 QCOMPARE(list[1], QVariant());
1218 QCOMPARE(list[2].type(), QVariant::List);
1219 QVariantList vlist = list[2].toList();
1220 QCOMPARE(vlist.size(), 4);
1221 QCOMPARE(vlist.at(0), QVariant(true));
1222 QCOMPARE(vlist.at(1), QVariant(999.));
1223 QCOMPARE(vlist.at(2), QVariant(QLatin1String("string")));
1224 QCOMPARE(vlist.at(3), QVariant());
1225 }
1226
toJson()1227 void tst_QtJson::toJson()
1228 {
1229 // Test QJsonDocument::Indented format
1230 {
1231 QJsonObject object;
1232 object.insert("\\Key\n", QString("Value"));
1233 object.insert("null", QJsonValue());
1234 QJsonArray array;
1235 array.append(true);
1236 array.append(999.);
1237 array.append(QLatin1String("string"));
1238 array.append(QJsonValue());
1239 array.append(QLatin1String("\\\a\n\r\b\tabcABC\""));
1240 object.insert("Array", array);
1241
1242 QByteArray json = QJsonDocument(object).toJson();
1243
1244 QByteArray expected =
1245 "{\n"
1246 " \"Array\": [\n"
1247 " true,\n"
1248 " 999,\n"
1249 " \"string\",\n"
1250 " null,\n"
1251 " \"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"\n"
1252 " ],\n"
1253 " \"\\\\Key\\n\": \"Value\",\n"
1254 " \"null\": null\n"
1255 "}\n";
1256 QCOMPARE(json, expected);
1257
1258 QJsonDocument doc;
1259 doc.setObject(object);
1260 json = doc.toJson();
1261 QCOMPARE(json, expected);
1262
1263 doc.setArray(array);
1264 json = doc.toJson();
1265 expected =
1266 "[\n"
1267 " true,\n"
1268 " 999,\n"
1269 " \"string\",\n"
1270 " null,\n"
1271 " \"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"\n"
1272 "]\n";
1273 QCOMPARE(json, expected);
1274 }
1275
1276 // Test QJsonDocument::Compact format
1277 {
1278 QJsonObject object;
1279 object.insert("\\Key\n", QString("Value"));
1280 object.insert("null", QJsonValue());
1281 QJsonArray array;
1282 array.append(true);
1283 array.append(999.);
1284 array.append(QLatin1String("string"));
1285 array.append(QJsonValue());
1286 array.append(QLatin1String("\\\a\n\r\b\tabcABC\""));
1287 object.insert("Array", array);
1288
1289 QByteArray json = QJsonDocument(object).toJson(QJsonDocument::Compact);
1290 QByteArray expected =
1291 "{\"Array\":[true,999,\"string\",null,\"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"],\"\\\\Key\\n\":\"Value\",\"null\":null}";
1292 QCOMPARE(json, expected);
1293
1294 QJsonDocument doc;
1295 doc.setObject(object);
1296 json = doc.toJson(QJsonDocument::Compact);
1297 QCOMPARE(json, expected);
1298
1299 doc.setArray(array);
1300 json = doc.toJson(QJsonDocument::Compact);
1301 expected = "[true,999,\"string\",null,\"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"]";
1302 QCOMPARE(json, expected);
1303 }
1304
1305 }
1306
toJsonSillyNumericValues()1307 void tst_QtJson::toJsonSillyNumericValues()
1308 {
1309 QJsonObject object;
1310 QJsonArray array;
1311 array.append(QJsonValue(std::numeric_limits<double>::infinity())); // encode to: null
1312 array.append(QJsonValue(-std::numeric_limits<double>::infinity())); // encode to: null
1313 array.append(QJsonValue(std::numeric_limits<double>::quiet_NaN())); // encode to: null
1314 object.insert("Array", array);
1315
1316 QByteArray json = QJsonDocument(object).toJson();
1317
1318 QByteArray expected =
1319 "{\n"
1320 " \"Array\": [\n"
1321 " null,\n"
1322 " null,\n"
1323 " null\n"
1324 " ]\n"
1325 "}\n";
1326
1327 QCOMPARE(json, expected);
1328
1329 QJsonDocument doc;
1330 doc.setObject(object);
1331 json = doc.toJson();
1332 QCOMPARE(json, expected);
1333 }
1334
toJsonLargeNumericValues()1335 void tst_QtJson::toJsonLargeNumericValues()
1336 {
1337 QJsonObject object;
1338 QJsonArray array;
1339 array.append(QJsonValue(1.234567)); // actual precision bug in Qt 5.0.0
1340 array.append(QJsonValue(1.7976931348623157e+308)); // JS Number.MAX_VALUE
1341 array.append(QJsonValue(5e-324)); // JS Number.MIN_VALUE
1342 array.append(QJsonValue(std::numeric_limits<double>::min()));
1343 array.append(QJsonValue(std::numeric_limits<double>::max()));
1344 array.append(QJsonValue(std::numeric_limits<double>::epsilon()));
1345 array.append(QJsonValue(std::numeric_limits<double>::denorm_min()));
1346 array.append(QJsonValue(0.0));
1347 array.append(QJsonValue(-std::numeric_limits<double>::min()));
1348 array.append(QJsonValue(-std::numeric_limits<double>::max()));
1349 array.append(QJsonValue(-std::numeric_limits<double>::epsilon()));
1350 array.append(QJsonValue(-std::numeric_limits<double>::denorm_min()));
1351 array.append(QJsonValue(-0.0));
1352 array.append(QJsonValue(9007199254740992LL)); // JS Number max integer
1353 array.append(QJsonValue(-9007199254740992LL)); // JS Number min integer
1354 object.insert("Array", array);
1355
1356 QByteArray json = QJsonDocument(object).toJson();
1357
1358 QByteArray expected =
1359 "{\n"
1360 " \"Array\": [\n"
1361 " 1.234567,\n"
1362 " 1.7976931348623157e+308,\n"
1363 // ((4.9406564584124654e-324 == 5e-324) == true)
1364 // I can only think JavaScript has a special formatter to
1365 // emit this value for this IEEE754 bit pattern.
1366 " 4.9406564584124654e-324,\n"
1367 " 2.2250738585072014e-308,\n"
1368 " 1.7976931348623157e+308,\n"
1369 " 2.2204460492503131e-16,\n"
1370 " 4.9406564584124654e-324,\n"
1371 " 0,\n"
1372 " -2.2250738585072014e-308,\n"
1373 " -1.7976931348623157e+308,\n"
1374 " -2.2204460492503131e-16,\n"
1375 " -4.9406564584124654e-324,\n"
1376 " 0,\n"
1377 " 9007199254740992,\n"
1378 " -9007199254740992\n"
1379 " ]\n"
1380 "}\n";
1381
1382 #ifdef Q_OS_QNX
1383 QEXPECT_FAIL("", "See QTBUG-37066", Continue);
1384 #endif
1385 QCOMPARE(json, expected);
1386
1387 QJsonDocument doc;
1388 doc.setObject(object);
1389 json = doc.toJson();
1390 #ifdef Q_OS_QNX
1391 QEXPECT_FAIL("", "See QTBUG-37066", Continue);
1392 #endif
1393 QCOMPARE(json, expected);
1394 }
1395
fromJson()1396 void tst_QtJson::fromJson()
1397 {
1398 {
1399 QByteArray json = "[\n true\n]\n";
1400 QJsonDocument doc = QJsonDocument::fromJson(json);
1401 QVERIFY(!doc.isEmpty());
1402 QCOMPARE(doc.isArray(), true);
1403 QCOMPARE(doc.isObject(), false);
1404 QJsonArray array = doc.array();
1405 QCOMPARE(array.size(), 1);
1406 QCOMPARE(array.at(0).type(), QJsonValue::Bool);
1407 QCOMPARE(array.at(0).toBool(), true);
1408 QCOMPARE(doc.toJson(), json);
1409 }
1410 /*{
1411 //regression test: test if unicode_control_characters are correctly decoded
1412 QByteArray json = "[\n \"" UNICODE_NON_CHARACTER "\"\n]\n";
1413 QJsonDocument doc = QJsonDocument::fromJson(json);
1414 QVERIFY(!doc.isEmpty());
1415 QCOMPARE(doc.isArray(), true);
1416 QCOMPARE(doc.isObject(), false);
1417 QJsonArray array = doc.array();
1418 QCOMPARE(array.size(), 1);
1419 QCOMPARE(array.at(0).type(), QJsonValue::String);
1420 QCOMPARE(array.at(0).toString(), QString::fromUtf8(UNICODE_NON_CHARACTER));
1421 QCOMPARE(doc.toJson(), json);
1422 }*/
1423 {
1424 QByteArray json = "[]";
1425 QJsonDocument doc = QJsonDocument::fromJson(json);
1426 QVERIFY(!doc.isEmpty());
1427 QCOMPARE(doc.isArray(), true);
1428 QCOMPARE(doc.isObject(), false);
1429 QJsonArray array = doc.array();
1430 QCOMPARE(array.size(), 0);
1431 }
1432 {
1433 QByteArray json = "{}";
1434 QJsonDocument doc = QJsonDocument::fromJson(json);
1435 QVERIFY(!doc.isEmpty());
1436 QCOMPARE(doc.isArray(), false);
1437 QCOMPARE(doc.isObject(), true);
1438 QJsonObject object = doc.object();
1439 QCOMPARE(object.size(), 0);
1440 }
1441 {
1442 QByteArray json = "{\n \"Key\": true\n}\n";
1443 QJsonDocument doc = QJsonDocument::fromJson(json);
1444 QVERIFY(!doc.isEmpty());
1445 QCOMPARE(doc.isArray(), false);
1446 QCOMPARE(doc.isObject(), true);
1447 QJsonObject object = doc.object();
1448 QCOMPARE(object.size(), 1);
1449 QCOMPARE(object.value("Key"), QJsonValue(true));
1450 QCOMPARE(doc.toJson(), json);
1451 }
1452 {
1453 QByteArray json = "[ null, true, false, \"Foo\", 1, [], {} ]";
1454 QJsonDocument doc = QJsonDocument::fromJson(json);
1455 QVERIFY(!doc.isEmpty());
1456 QCOMPARE(doc.isArray(), true);
1457 QCOMPARE(doc.isObject(), false);
1458 QJsonArray array = doc.array();
1459 QCOMPARE(array.size(), 7);
1460 QCOMPARE(array.at(0).type(), QJsonValue::Null);
1461 QCOMPARE(array.at(1).type(), QJsonValue::Bool);
1462 QCOMPARE(array.at(1).toBool(), true);
1463 QCOMPARE(array.at(2).type(), QJsonValue::Bool);
1464 QCOMPARE(array.at(2).toBool(), false);
1465 QCOMPARE(array.at(3).type(), QJsonValue::String);
1466 QCOMPARE(array.at(3).toString(), QLatin1String("Foo"));
1467 QCOMPARE(array.at(4).type(), QJsonValue::Double);
1468 QCOMPARE(array.at(4).toDouble(), 1.);
1469 QCOMPARE(array.at(5).type(), QJsonValue::Array);
1470 QCOMPARE(array.at(5).toArray().size(), 0);
1471 QCOMPARE(array.at(6).type(), QJsonValue::Object);
1472 QCOMPARE(array.at(6).toObject().size(), 0);
1473 }
1474 {
1475 QByteArray json = "{ \"0\": null, \"1\": true, \"2\": false, \"3\": \"Foo\", \"4\": 1, \"5\": [], \"6\": {} }";
1476 QJsonDocument doc = QJsonDocument::fromJson(json);
1477 QVERIFY(!doc.isEmpty());
1478 QCOMPARE(doc.isArray(), false);
1479 QCOMPARE(doc.isObject(), true);
1480 QJsonObject object = doc.object();
1481 QCOMPARE(object.size(), 7);
1482 QCOMPARE(object.value("0").type(), QJsonValue::Null);
1483 QCOMPARE(object.value("1").type(), QJsonValue::Bool);
1484 QCOMPARE(object.value("1").toBool(), true);
1485 QCOMPARE(object.value("2").type(), QJsonValue::Bool);
1486 QCOMPARE(object.value("2").toBool(), false);
1487 QCOMPARE(object.value("3").type(), QJsonValue::String);
1488 QCOMPARE(object.value("3").toString(), QLatin1String("Foo"));
1489 QCOMPARE(object.value("4").type(), QJsonValue::Double);
1490 QCOMPARE(object.value("4").toDouble(), 1.);
1491 QCOMPARE(object.value("5").type(), QJsonValue::Array);
1492 QCOMPARE(object.value("5").toArray().size(), 0);
1493 QCOMPARE(object.value("6").type(), QJsonValue::Object);
1494 QCOMPARE(object.value("6").toObject().size(), 0);
1495 }
1496 {
1497 QByteArray compactJson = "{\"Array\": [true,999,\"string\",null,\"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"],\"\\\\Key\\n\": \"Value\",\"null\": null}";
1498 QJsonDocument doc = QJsonDocument::fromJson(compactJson);
1499 QVERIFY(!doc.isEmpty());
1500 QCOMPARE(doc.isArray(), false);
1501 QCOMPARE(doc.isObject(), true);
1502 QJsonObject object = doc.object();
1503 QCOMPARE(object.size(), 3);
1504 QCOMPARE(object.value("\\Key\n").isString(), true);
1505 QCOMPARE(object.value("\\Key\n").toString(), QString("Value"));
1506 QCOMPARE(object.value("null").isNull(), true);
1507 QCOMPARE(object.value("Array").isArray(), true);
1508 QJsonArray array = object.value("Array").toArray();
1509 QCOMPARE(array.size(), 5);
1510 QCOMPARE(array.at(0).isBool(), true);
1511 QCOMPARE(array.at(0).toBool(), true);
1512 QCOMPARE(array.at(1).isDouble(), true);
1513 QCOMPARE(array.at(1).toDouble(), 999.);
1514 QCOMPARE(array.at(2).isString(), true);
1515 QCOMPARE(array.at(2).toString(), QLatin1String("string"));
1516 QCOMPARE(array.at(3).isNull(), true);
1517 QCOMPARE(array.at(4).isString(), true);
1518 QCOMPARE(array.at(4).toString(), QLatin1String("\\\a\n\r\b\tabcABC\""));
1519 }
1520 }
1521
fromJsonErrors()1522 void tst_QtJson::fromJsonErrors()
1523 {
1524 {
1525 QJsonParseError error;
1526 QByteArray json = "{\n \n\n";
1527 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1528 QVERIFY(doc.isEmpty());
1529 QCOMPARE(error.error, QJsonParseError::UnterminatedObject);
1530 QCOMPARE(error.offset, 8);
1531 }
1532 {
1533 QJsonParseError error;
1534 QByteArray json = "{\n \"key\" 10\n";
1535 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1536 QVERIFY(doc.isEmpty());
1537 QCOMPARE(error.error, QJsonParseError::MissingNameSeparator);
1538 QCOMPARE(error.offset, 13);
1539 }
1540 {
1541 QJsonParseError error;
1542 QByteArray json = "[\n \n\n";
1543 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1544 QVERIFY(doc.isEmpty());
1545 QCOMPARE(error.error, QJsonParseError::UnterminatedArray);
1546 QCOMPARE(error.offset, 8);
1547 }
1548 {
1549 QJsonParseError error;
1550 QByteArray json = "[\n 1, true\n\n";
1551 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1552 QVERIFY(doc.isEmpty());
1553 QCOMPARE(error.error, QJsonParseError::UnterminatedArray);
1554 QCOMPARE(error.offset, 14);
1555 }
1556 {
1557 QJsonParseError error;
1558 QByteArray json = "[\n 1 true\n\n";
1559 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1560 QVERIFY(doc.isEmpty());
1561 QCOMPARE(error.error, QJsonParseError::MissingValueSeparator);
1562 QCOMPARE(error.offset, 7);
1563 }
1564 {
1565 QJsonParseError error;
1566 QByteArray json = "[\n nul";
1567 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1568 QVERIFY(doc.isEmpty());
1569 QCOMPARE(error.error, QJsonParseError::IllegalValue);
1570 QCOMPARE(error.offset, 7);
1571 }
1572 {
1573 QJsonParseError error;
1574 QByteArray json = "[\n nulzz";
1575 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1576 QVERIFY(doc.isEmpty());
1577 QCOMPARE(error.error, QJsonParseError::IllegalValue);
1578 QCOMPARE(error.offset, 10);
1579 }
1580 {
1581 QJsonParseError error;
1582 QByteArray json = "[\n tru";
1583 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1584 QVERIFY(doc.isEmpty());
1585 QCOMPARE(error.error, QJsonParseError::IllegalValue);
1586 QCOMPARE(error.offset, 7);
1587 }
1588 {
1589 QJsonParseError error;
1590 QByteArray json = "[\n trud]";
1591 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1592 QVERIFY(doc.isEmpty());
1593 QCOMPARE(error.error, QJsonParseError::IllegalValue);
1594 QCOMPARE(error.offset, 10);
1595 }
1596 {
1597 QJsonParseError error;
1598 QByteArray json = "[\n fal";
1599 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1600 QVERIFY(doc.isEmpty());
1601 QCOMPARE(error.error, QJsonParseError::IllegalValue);
1602 QCOMPARE(error.offset, 7);
1603 }
1604 {
1605 QJsonParseError error;
1606 QByteArray json = "[\n falsd]";
1607 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1608 QVERIFY(doc.isEmpty());
1609 QCOMPARE(error.error, QJsonParseError::IllegalValue);
1610 QCOMPARE(error.offset, 11);
1611 }
1612 {
1613 QJsonParseError error;
1614 QByteArray json = "[\n 11111";
1615 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1616 QVERIFY(doc.isEmpty());
1617 QCOMPARE(error.error, QJsonParseError::TerminationByNumber);
1618 QCOMPARE(error.offset, 11);
1619 }
1620 {
1621 QJsonParseError error;
1622 QByteArray json = "[\n -1E10000]";
1623 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1624 QVERIFY(doc.isEmpty());
1625 QCOMPARE(error.error, QJsonParseError::IllegalNumber);
1626 QCOMPARE(error.offset, 14);
1627 }
1628 {
1629 QJsonParseError error;
1630 QByteArray json = "[\n -1e-10000]";
1631 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1632 QVERIFY(doc.isEmpty());
1633 QCOMPARE(error.error, QJsonParseError::IllegalNumber);
1634 QCOMPARE(error.offset, 15);
1635 }
1636 {
1637 QJsonParseError error;
1638 QByteArray json = "[\n \"\\u12\"]";
1639 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1640 QVERIFY(doc.isEmpty());
1641 QCOMPARE(error.error, QJsonParseError::IllegalEscapeSequence);
1642 QCOMPARE(error.offset, 11);
1643 }
1644 {
1645 QJsonParseError error;
1646 QByteArray json = "[\n \"foo" INVALID_UNICODE "bar\"]";
1647 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1648 QVERIFY(doc.isEmpty());
1649 QCOMPARE(error.error, QJsonParseError::IllegalUTF8String);
1650 QCOMPARE(error.offset, 14);
1651 }
1652 {
1653 QJsonParseError error;
1654 QByteArray json = "[\n \"";
1655 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1656 QVERIFY(doc.isEmpty());
1657 QCOMPARE(error.error, QJsonParseError::UnterminatedString);
1658 QCOMPARE(error.offset, 8);
1659 }
1660 {
1661 QJsonParseError error;
1662 QByteArray json = "[\n \"c" UNICODE_DJE "a\\u12\"]";
1663 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1664 QVERIFY(doc.isEmpty());
1665 QCOMPARE(error.error, QJsonParseError::IllegalEscapeSequence);
1666 QCOMPARE(error.offset, 15);
1667 }
1668 {
1669 QJsonParseError error;
1670 QByteArray json = "[\n \"c" UNICODE_DJE "a" INVALID_UNICODE "bar\"]";
1671 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1672 QVERIFY(doc.isEmpty());
1673 QCOMPARE(error.error, QJsonParseError::IllegalUTF8String);
1674 QCOMPARE(error.offset, 15);
1675 }
1676 {
1677 QJsonParseError error;
1678 QByteArray json = "[\n \"c" UNICODE_DJE "a ]";
1679 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1680 QVERIFY(doc.isEmpty());
1681 QCOMPARE(error.error, QJsonParseError::UnterminatedString);
1682 QCOMPARE(error.offset, 14);
1683 }
1684 }
1685
fromBinary()1686 void tst_QtJson::fromBinary()
1687 {
1688 QFile file(":/test.json");
1689 file.open(QFile::ReadOnly);
1690 QByteArray testJson = file.readAll();
1691
1692 QJsonDocument doc = QJsonDocument::fromJson(testJson);
1693 QJsonDocument outdoc = QJsonDocument::fromBinaryData(doc.toBinaryData());
1694 QVERIFY(!outdoc.isNull());
1695 QVERIFY(doc == outdoc);
1696
1697 QFile bfile(":/test.bjson");
1698 bfile.open(QFile::ReadOnly);
1699 QByteArray binary = bfile.readAll();
1700
1701 QJsonDocument bdoc = QJsonDocument::fromBinaryData(binary);
1702 QVERIFY(!bdoc.isNull());
1703 QVERIFY(doc.toVariant() == bdoc.toVariant());
1704 QVERIFY(doc == bdoc);
1705 }
1706
toAndFromBinary_data()1707 void tst_QtJson::toAndFromBinary_data()
1708 {
1709 QTest::addColumn<QString>("filename");
1710 QTest::newRow("test.json") << (":/test.json");
1711 QTest::newRow("test2.json") << (":/test2.json");
1712 }
1713
toAndFromBinary()1714 void tst_QtJson::toAndFromBinary()
1715 {
1716 QFETCH(QString, filename);
1717 QFile file(filename);
1718 QVERIFY(file.open(QFile::ReadOnly));
1719 QByteArray data = file.readAll();
1720
1721 QJsonDocument doc = QJsonDocument::fromJson(data);
1722 QVERIFY(!doc.isNull());
1723 QJsonDocument outdoc = QJsonDocument::fromBinaryData(doc.toBinaryData());
1724 QVERIFY(!outdoc.isNull());
1725 QVERIFY(doc == outdoc);
1726 }
1727
parseNumbers()1728 void tst_QtJson::parseNumbers()
1729 {
1730 {
1731 // test number parsing
1732 struct Numbers {
1733 const char *str;
1734 int n;
1735 };
1736 Numbers numbers [] = {
1737 { "0", 0 },
1738 { "1", 1 },
1739 { "10", 10 },
1740 { "-1", -1 },
1741 { "100000", 100000 },
1742 { "-999", -999 }
1743 };
1744 int size = sizeof(numbers)/sizeof(Numbers);
1745 for (int i = 0; i < size; ++i) {
1746 QByteArray json = "[ ";
1747 json += numbers[i].str;
1748 json += " ]";
1749 QJsonDocument doc = QJsonDocument::fromJson(json);
1750 QVERIFY(!doc.isEmpty());
1751 QCOMPARE(doc.isArray(), true);
1752 QCOMPARE(doc.isObject(), false);
1753 QJsonArray array = doc.array();
1754 QCOMPARE(array.size(), 1);
1755 QJsonValue val = array.at(0);
1756 QCOMPARE(val.type(), QJsonValue::Double);
1757 QCOMPARE(val.toDouble(), (double)numbers[i].n);
1758 }
1759 }
1760 {
1761 // test number parsing
1762 struct Numbers {
1763 const char *str;
1764 double n;
1765 };
1766 Numbers numbers [] = {
1767 { "0", 0 },
1768 { "1", 1 },
1769 { "10", 10 },
1770 { "-1", -1 },
1771 { "100000", 100000 },
1772 { "-999", -999 },
1773 { "1.1", 1.1 },
1774 { "1e10", 1e10 },
1775 { "-1.1", -1.1 },
1776 { "-1e10", -1e10 },
1777 { "-1E10", -1e10 },
1778 { "1.1e10", 1.1e10 },
1779 { "1.1e308", 1.1e308 },
1780 { "-1.1e308", -1.1e308 },
1781 { "1.1e-308", 1.1e-308 },
1782 { "-1.1e-308", -1.1e-308 },
1783 { "1.1e+308", 1.1e+308 },
1784 { "-1.1e+308", -1.1e+308 },
1785 { "1.e+308", 1.e+308 },
1786 { "-1.e+308", -1.e+308 }
1787 };
1788 int size = sizeof(numbers)/sizeof(Numbers);
1789 for (int i = 0; i < size; ++i) {
1790 QByteArray json = "[ ";
1791 json += numbers[i].str;
1792 json += " ]";
1793 QJsonDocument doc = QJsonDocument::fromJson(json);
1794 #ifdef Q_OS_QNX
1795 if (0 == QString::compare(numbers[i].str, "1.1e-308"))
1796 QEXPECT_FAIL("", "See QTBUG-37066", Abort);
1797 #endif
1798 QVERIFY(!doc.isEmpty());
1799 QCOMPARE(doc.isArray(), true);
1800 QCOMPARE(doc.isObject(), false);
1801 QJsonArray array = doc.array();
1802 QCOMPARE(array.size(), 1);
1803 QJsonValue val = array.at(0);
1804 QCOMPARE(val.type(), QJsonValue::Double);
1805 QCOMPARE(val.toDouble(), numbers[i].n);
1806 }
1807 }
1808 }
1809
parseStrings()1810 void tst_QtJson::parseStrings()
1811 {
1812 const char *strings [] =
1813 {
1814 "Foo",
1815 "abc\\\"abc",
1816 "abc\\\\abc",
1817 "abc\\babc",
1818 "abc\\fabc",
1819 "abc\\nabc",
1820 "abc\\rabc",
1821 "abc\\tabc",
1822 "abc\\u0019abc"
1823 // "abc" UNICODE_DJE "abc",
1824 // UNICODE_NON_CHARACTER
1825 };
1826 int size = sizeof(strings)/sizeof(const char *);
1827
1828 for (int i = 0; i < size; ++i) {
1829 QByteArray json = "[\n \"";
1830 json += strings[i];
1831 json += "\"\n]\n";
1832 QJsonDocument doc = QJsonDocument::fromJson(json);
1833 QVERIFY(!doc.isEmpty());
1834 QCOMPARE(doc.isArray(), true);
1835 QCOMPARE(doc.isObject(), false);
1836 QJsonArray array = doc.array();
1837 QCOMPARE(array.size(), 1);
1838 QJsonValue val = array.at(0);
1839 QCOMPARE(val.type(), QJsonValue::String);
1840
1841 QCOMPARE(doc.toJson(), json);
1842 }
1843
1844 struct Pairs {
1845 const char *in;
1846 const char *out;
1847 };
1848 Pairs pairs [] = {
1849 { "abc\\/abc", "abc/abc" },
1850 // { "abc\\u0402abc", "abc" UNICODE_DJE "abc" },
1851 { "abc\\u0065abc", "abceabc" }
1852 // { "abc\\uFFFFabc", "abc" UNICODE_NON_CHARACTER "abc" }
1853 };
1854 size = sizeof(pairs)/sizeof(Pairs);
1855
1856 for (int i = 0; i < size; ++i) {
1857 QByteArray json = "[\n \"";
1858 json += pairs[i].in;
1859 json += "\"\n]\n";
1860 QByteArray out = "[\n \"";
1861 out += pairs[i].out;
1862 out += "\"\n]\n";
1863 QJsonDocument doc = QJsonDocument::fromJson(json);
1864 QVERIFY(!doc.isEmpty());
1865 QCOMPARE(doc.isArray(), true);
1866 QCOMPARE(doc.isObject(), false);
1867 QJsonArray array = doc.array();
1868 QCOMPARE(array.size(), 1);
1869 QJsonValue val = array.at(0);
1870 QCOMPARE(val.type(), QJsonValue::String);
1871
1872 QCOMPARE(doc.toJson(), out);
1873 }
1874
1875 }
1876
parseDuplicateKeys()1877 void tst_QtJson::parseDuplicateKeys()
1878 {
1879 const char *json = "{ \"B\": true, \"A\": null, \"B\": false }";
1880
1881 QJsonDocument doc = QJsonDocument::fromJson(json);
1882 QCOMPARE(doc.isObject(), true);
1883
1884 QJsonObject o = doc.object();
1885 QCOMPARE(o.size(), 2);
1886 QJsonObject::const_iterator it = o.constBegin();
1887 QCOMPARE(it.key(), QLatin1String("A"));
1888 QCOMPARE(it.value(), QJsonValue());
1889 ++it;
1890 QCOMPARE(it.key(), QLatin1String("B"));
1891 QCOMPARE(it.value(), QJsonValue(false));
1892 }
1893
testParser()1894 void tst_QtJson::testParser()
1895 {
1896 QFile file(":/test.json");
1897 file.open(QFile::ReadOnly);
1898 QByteArray testJson = file.readAll();
1899
1900 QJsonDocument doc = QJsonDocument::fromJson(testJson);
1901 QVERIFY(!doc.isEmpty());
1902 }
1903
compactArray()1904 void tst_QtJson::compactArray()
1905 {
1906 QJsonArray array;
1907 array.append(QLatin1String("First Entry"));
1908 array.append(QLatin1String("Second Entry"));
1909 array.append(QLatin1String("Third Entry"));
1910 QJsonDocument doc(array);
1911 int s = doc.toBinaryData().size();
1912 array.removeAt(1);
1913 doc.setArray(array);
1914 QVERIFY(s > doc.toBinaryData().size());
1915 s = doc.toBinaryData().size();
1916 QCOMPARE(doc.toJson(),
1917 QByteArray("[\n"
1918 " \"First Entry\",\n"
1919 " \"Third Entry\"\n"
1920 "]\n"));
1921
1922 array.removeAt(0);
1923 doc.setArray(array);
1924 QVERIFY(s > doc.toBinaryData().size());
1925 s = doc.toBinaryData().size();
1926 QCOMPARE(doc.toJson(),
1927 QByteArray("[\n"
1928 " \"Third Entry\"\n"
1929 "]\n"));
1930
1931 array.removeAt(0);
1932 doc.setArray(array);
1933 QVERIFY(s > doc.toBinaryData().size());
1934 s = doc.toBinaryData().size();
1935 QCOMPARE(doc.toJson(),
1936 QByteArray("[\n"
1937 "]\n"));
1938
1939 }
1940
compactObject()1941 void tst_QtJson::compactObject()
1942 {
1943 QJsonObject object;
1944 object.insert(QLatin1String("Key1"), QLatin1String("First Entry"));
1945 object.insert(QLatin1String("Key2"), QLatin1String("Second Entry"));
1946 object.insert(QLatin1String("Key3"), QLatin1String("Third Entry"));
1947 QJsonDocument doc(object);
1948 int s = doc.toBinaryData().size();
1949 object.remove(QLatin1String("Key2"));
1950 doc.setObject(object);
1951 QVERIFY(s > doc.toBinaryData().size());
1952 s = doc.toBinaryData().size();
1953 QCOMPARE(doc.toJson(),
1954 QByteArray("{\n"
1955 " \"Key1\": \"First Entry\",\n"
1956 " \"Key3\": \"Third Entry\"\n"
1957 "}\n"));
1958
1959 object.remove(QLatin1String("Key1"));
1960 doc.setObject(object);
1961 QVERIFY(s > doc.toBinaryData().size());
1962 s = doc.toBinaryData().size();
1963 QCOMPARE(doc.toJson(),
1964 QByteArray("{\n"
1965 " \"Key3\": \"Third Entry\"\n"
1966 "}\n"));
1967
1968 object.remove(QLatin1String("Key3"));
1969 doc.setObject(object);
1970 QVERIFY(s > doc.toBinaryData().size());
1971 s = doc.toBinaryData().size();
1972 QCOMPARE(doc.toJson(),
1973 QByteArray("{\n"
1974 "}\n"));
1975
1976 }
1977
validation()1978 void tst_QtJson::validation()
1979 {
1980 // this basically tests that we don't crash on corrupt data
1981 QFile file(":/test.json");
1982 QVERIFY(file.open(QFile::ReadOnly));
1983 QByteArray testJson = file.readAll();
1984 QVERIFY(!testJson.isEmpty());
1985
1986 QJsonDocument doc = QJsonDocument::fromJson(testJson);
1987 QVERIFY(!doc.isNull());
1988
1989 QByteArray binary = doc.toBinaryData();
1990
1991 // only test the first 1000 bytes. Testing the full file takes too long
1992 for (int i = 0; i < 1000; ++i) {
1993 QByteArray corrupted = binary;
1994 corrupted[i] = char(0xff);
1995 QJsonDocument doc = QJsonDocument::fromBinaryData(corrupted);
1996 if (doc.isNull())
1997 continue;
1998 QByteArray json = doc.toJson();
1999 }
2000
2001
2002 QFile file2(":/test3.json");
2003 file2.open(QFile::ReadOnly);
2004 testJson = file2.readAll();
2005 QVERIFY(!testJson.isEmpty());
2006
2007 doc = QJsonDocument::fromJson(testJson);
2008 QVERIFY(!doc.isNull());
2009
2010 binary = doc.toBinaryData();
2011
2012 for (int i = 0; i < binary.size(); ++i) {
2013 QByteArray corrupted = binary;
2014 corrupted[i] = char(0xff);
2015 QJsonDocument doc = QJsonDocument::fromBinaryData(corrupted);
2016 if (doc.isNull())
2017 continue;
2018 QByteArray json = doc.toJson();
2019
2020 corrupted = binary;
2021 corrupted[i] = 0x00;
2022 doc = QJsonDocument::fromBinaryData(corrupted);
2023 if (doc.isNull())
2024 continue;
2025 json = doc.toJson();
2026 }
2027 }
2028
assignToDocument()2029 void tst_QtJson::assignToDocument()
2030 {
2031 {
2032 const char *json = "{ \"inner\": { \"key\": true } }";
2033 QJsonDocument doc = QJsonDocument::fromJson(json);
2034
2035 QJsonObject o = doc.object();
2036 QJsonValue inner = o.value("inner");
2037
2038 QJsonDocument innerDoc(inner.toObject());
2039
2040 QVERIFY(innerDoc != doc);
2041 QVERIFY(innerDoc.object() == inner.toObject());
2042 }
2043 {
2044 const char *json = "[ [ true ] ]";
2045 QJsonDocument doc = QJsonDocument::fromJson(json);
2046
2047 QJsonArray a = doc.array();
2048 QJsonValue inner = a.at(0);
2049
2050 QJsonDocument innerDoc(inner.toArray());
2051
2052 QVERIFY(innerDoc != doc);
2053 QVERIFY(innerDoc.array() == inner.toArray());
2054 }
2055 }
2056
2057
testDuplicateKeys()2058 void tst_QtJson::testDuplicateKeys()
2059 {
2060 QJsonObject obj;
2061 obj.insert(QLatin1String("foo"), QLatin1String("bar"));
2062 obj.insert(QLatin1String("foo"), QLatin1String("zap"));
2063 QCOMPARE(obj.size(), 1);
2064 QCOMPARE(obj.value(QLatin1String("foo")).toString(), QLatin1String("zap"));
2065 }
2066
testCompaction()2067 void tst_QtJson::testCompaction()
2068 {
2069 // modify object enough times to trigger compactionCounter
2070 // and make sure the data is still valid
2071 QJsonObject obj;
2072 for (int i = 0; i < 33; ++i) {
2073 obj.remove(QLatin1String("foo"));
2074 obj.insert(QLatin1String("foo"), QLatin1String("bar"));
2075 }
2076 QCOMPARE(obj.size(), 1);
2077 QCOMPARE(obj.value(QLatin1String("foo")).toString(), QLatin1String("bar"));
2078
2079 QJsonDocument doc = QJsonDocument::fromBinaryData(QJsonDocument(obj).toBinaryData());
2080 QVERIFY(!doc.isNull());
2081 QVERIFY(!doc.isEmpty());
2082 QCOMPARE(doc.isArray(), false);
2083 QCOMPARE(doc.isObject(), true);
2084 QVERIFY(doc.object() == obj);
2085 }
2086
testDebugStream()2087 void tst_QtJson::testDebugStream()
2088 {
2089 {
2090 // QJsonObject
2091
2092 QJsonObject object;
2093 QTest::ignoreMessage(QtDebugMsg, "QJsonObject() ");
2094 qDebug() << object;
2095
2096 object.insert(QLatin1String("foo"), QLatin1String("bar"));
2097 QTest::ignoreMessage(QtDebugMsg, "QJsonObject({\"foo\":\"bar\"}) ");
2098 qDebug() << object;
2099 }
2100
2101 {
2102 // QJsonArray
2103
2104 QJsonArray array;
2105 QTest::ignoreMessage(QtDebugMsg, "QJsonArray() ");
2106 qDebug() << array;
2107
2108 array.append(1);
2109 array.append(QLatin1String("foo"));
2110 QTest::ignoreMessage(QtDebugMsg, "QJsonArray([1,\"foo\"]) ");
2111 qDebug() << array;
2112 }
2113
2114 {
2115 // QJsonDocument
2116
2117 QJsonDocument doc;
2118 QTest::ignoreMessage(QtDebugMsg, "QJsonDocument() ");
2119 qDebug() << doc;
2120
2121 QJsonObject object;
2122 object.insert(QLatin1String("foo"), QLatin1String("bar"));
2123 doc.setObject(object);
2124 QTest::ignoreMessage(QtDebugMsg, "QJsonDocument({\"foo\":\"bar\"}) ");
2125 qDebug() << doc;
2126
2127 QJsonArray array;
2128 array.append(1);
2129 array.append(QLatin1String("foo"));
2130 QTest::ignoreMessage(QtDebugMsg, "QJsonDocument([1,\"foo\"]) ");
2131 doc.setArray(array);
2132 qDebug() << doc;
2133 }
2134
2135 {
2136 // QJsonValue
2137
2138 QJsonValue value;
2139
2140 QTest::ignoreMessage(QtDebugMsg, "QJsonValue(null) ");
2141 qDebug() << value;
2142
2143 value = QJsonValue(true); // bool
2144 QTest::ignoreMessage(QtDebugMsg, "QJsonValue(bool, true) ");
2145 qDebug() << value;
2146
2147 value = QJsonValue((double)4.2); // double
2148 QTest::ignoreMessage(QtDebugMsg, "QJsonValue(double, 4.2) ");
2149 qDebug() << value;
2150
2151 value = QJsonValue((int)42); // int
2152 QTest::ignoreMessage(QtDebugMsg, "QJsonValue(double, 42) ");
2153 qDebug() << value;
2154
2155 value = QJsonValue(QLatin1String("foo")); // string
2156 QTest::ignoreMessage(QtDebugMsg, "QJsonValue(string, \"foo\") ");
2157 qDebug() << value;
2158
2159 QJsonArray array;
2160 array.append(1);
2161 array.append(QLatin1String("foo"));
2162 value = QJsonValue(array); // array
2163 QTest::ignoreMessage(QtDebugMsg, "QJsonValue(array, QJsonArray([1,\"foo\"]) ) ");
2164 qDebug() << value;
2165
2166 QJsonObject object;
2167 object.insert(QLatin1String("foo"), QLatin1String("bar"));
2168 value = QJsonValue(object); // object
2169 QTest::ignoreMessage(QtDebugMsg, "QJsonValue(object, QJsonObject({\"foo\":\"bar\"}) ) ");
2170 qDebug() << value;
2171 }
2172 }
2173
testCompactionError()2174 void tst_QtJson::testCompactionError()
2175 {
2176 QJsonObject schemaObject;
2177 schemaObject.insert("_Type", QLatin1String("_SchemaType"));
2178 schemaObject.insert("name", QLatin1String("Address"));
2179 schemaObject.insert("schema", QJsonObject());
2180 {
2181 QJsonObject content(schemaObject);
2182 QJsonDocument doc(content);
2183 QVERIFY(!doc.isNull());
2184 QByteArray hash = QCryptographicHash::hash(doc.toBinaryData(), QCryptographicHash::Md5).toHex();
2185 schemaObject.insert("_Version", QString::fromLatin1(hash.constData(), hash.size()));
2186 }
2187
2188 QJsonObject schema;
2189 schema.insert("streetNumber", schema.value("number").toObject());
2190 schemaObject.insert("schema", schema);
2191 {
2192 QJsonObject content(schemaObject);
2193 content.remove("_Uuid");
2194 content.remove("_Version");
2195 QJsonDocument doc(content);
2196 QVERIFY(!doc.isNull());
2197 QByteArray hash = QCryptographicHash::hash(doc.toBinaryData(), QCryptographicHash::Md5).toHex();
2198 schemaObject.insert("_Version", QString::fromLatin1(hash.constData(), hash.size()));
2199 }
2200 }
2201
parseUnicodeEscapes()2202 void tst_QtJson::parseUnicodeEscapes()
2203 {
2204 const QByteArray json = "[ \"A\\u00e4\\u00C4\" ]";
2205
2206 QJsonDocument doc = QJsonDocument::fromJson(json);
2207 QJsonArray array = doc.array();
2208
2209 QString result = QLatin1String("A");
2210 result += QChar(0xe4);
2211 result += QChar(0xc4);
2212
2213 QCOMPARE(array.first().toString(), result);
2214 }
2215
assignObjects()2216 void tst_QtJson::assignObjects()
2217 {
2218 const char *json =
2219 "[ { \"Key\": 1 }, { \"Key\": 2 } ]";
2220
2221 QJsonDocument doc = QJsonDocument::fromJson(json);
2222 QJsonArray array = doc.array();
2223
2224 QJsonObject object = array.at(0).toObject();
2225 QCOMPARE(object.value("Key").toDouble(), 1.);
2226
2227 object = array.at(1).toObject();
2228 QCOMPARE(object.value("Key").toDouble(), 2.);
2229 }
2230
assignArrays()2231 void tst_QtJson::assignArrays()
2232 {
2233 const char *json =
2234 "[ [ 1 ], [ 2 ] ]";
2235
2236 QJsonDocument doc = QJsonDocument::fromJson(json);
2237 QJsonArray array = doc.array();
2238
2239 QJsonArray inner = array.at(0).toArray() ;
2240 QCOMPARE(inner.at(0).toDouble(), 1.);
2241
2242 inner= array.at(1).toArray();
2243 QCOMPARE(inner.at(0).toDouble(), 2.);
2244 }
2245
testTrailingComma()2246 void tst_QtJson::testTrailingComma()
2247 {
2248 const char *jsons[] = { "{ \"Key\": 1, }", "[ { \"Key\": 1 }, ]" };
2249
2250 for (unsigned i = 0; i < sizeof(jsons)/sizeof(jsons[0]); ++i) {
2251 QJsonParseError error;
2252 QJsonDocument doc = QJsonDocument::fromJson(jsons[i], &error);
2253 QCOMPARE(error.error, QJsonParseError::MissingObject);
2254 }
2255 }
2256
testDetachBug()2257 void tst_QtJson::testDetachBug()
2258 {
2259 QJsonObject dynamic;
2260 QJsonObject embedded;
2261
2262 QJsonObject local;
2263
2264 embedded.insert("Key1", QString("Value1"));
2265 embedded.insert("Key2", QString("Value2"));
2266 dynamic.insert(QLatin1String("Bogus"), QString("bogusValue"));
2267 dynamic.insert("embedded", embedded);
2268 local = dynamic.value("embedded").toObject();
2269
2270 dynamic.remove("embedded");
2271
2272 QCOMPARE(local.keys().size(),2);
2273 local.remove("Key1");
2274 local.remove("Key2");
2275 QCOMPARE(local.keys().size(), 0);
2276
2277 local.insert("Key1", QString("anotherValue"));
2278 QCOMPARE(local.keys().size(), 1);
2279 }
2280
valueEquals()2281 void tst_QtJson::valueEquals()
2282 {
2283 QVERIFY(QJsonValue() == QJsonValue());
2284 QVERIFY(QJsonValue() != QJsonValue(QJsonValue::Undefined));
2285 QVERIFY(QJsonValue() != QJsonValue(true));
2286 QVERIFY(QJsonValue() != QJsonValue(1.));
2287 QVERIFY(QJsonValue() != QJsonValue(QJsonArray()));
2288 QVERIFY(QJsonValue() != QJsonValue(QJsonObject()));
2289
2290 QVERIFY(QJsonValue(true) == QJsonValue(true));
2291 QVERIFY(QJsonValue(true) != QJsonValue(false));
2292 QVERIFY(QJsonValue(true) != QJsonValue(QJsonValue::Undefined));
2293 QVERIFY(QJsonValue(true) != QJsonValue());
2294 QVERIFY(QJsonValue(true) != QJsonValue(1.));
2295 QVERIFY(QJsonValue(true) != QJsonValue(QJsonArray()));
2296 QVERIFY(QJsonValue(true) != QJsonValue(QJsonObject()));
2297
2298 QVERIFY(QJsonValue(1) == QJsonValue(1));
2299 QVERIFY(QJsonValue(1) != QJsonValue(2));
2300 QVERIFY(QJsonValue(1) == QJsonValue(1.));
2301 QVERIFY(QJsonValue(1) != QJsonValue(1.1));
2302 QVERIFY(QJsonValue(1) != QJsonValue(QJsonValue::Undefined));
2303 QVERIFY(QJsonValue(1) != QJsonValue());
2304 QVERIFY(QJsonValue(1) != QJsonValue(true));
2305 QVERIFY(QJsonValue(1) != QJsonValue(QJsonArray()));
2306 QVERIFY(QJsonValue(1) != QJsonValue(QJsonObject()));
2307
2308 QVERIFY(QJsonValue(1.) == QJsonValue(1.));
2309 QVERIFY(QJsonValue(1.) != QJsonValue(2.));
2310 QVERIFY(QJsonValue(1.) != QJsonValue(QJsonValue::Undefined));
2311 QVERIFY(QJsonValue(1.) != QJsonValue());
2312 QVERIFY(QJsonValue(1.) != QJsonValue(true));
2313 QVERIFY(QJsonValue(1.) != QJsonValue(QJsonArray()));
2314 QVERIFY(QJsonValue(1.) != QJsonValue(QJsonObject()));
2315
2316 QVERIFY(QJsonValue(QJsonArray()) == QJsonValue(QJsonArray()));
2317 QJsonArray nonEmptyArray;
2318 nonEmptyArray.append(true);
2319 QVERIFY(QJsonValue(QJsonArray()) != nonEmptyArray);
2320 QVERIFY(QJsonValue(QJsonArray()) != QJsonValue(QJsonValue::Undefined));
2321 QVERIFY(QJsonValue(QJsonArray()) != QJsonValue());
2322 QVERIFY(QJsonValue(QJsonArray()) != QJsonValue(true));
2323 QVERIFY(QJsonValue(QJsonArray()) != QJsonValue(1.));
2324 QVERIFY(QJsonValue(QJsonArray()) != QJsonValue(QJsonObject()));
2325
2326 QVERIFY(QJsonValue(QJsonObject()) == QJsonValue(QJsonObject()));
2327 QJsonObject nonEmptyObject;
2328 nonEmptyObject.insert("Key", true);
2329 QVERIFY(QJsonValue(QJsonObject()) != nonEmptyObject);
2330 QVERIFY(QJsonValue(QJsonObject()) != QJsonValue(QJsonValue::Undefined));
2331 QVERIFY(QJsonValue(QJsonObject()) != QJsonValue());
2332 QVERIFY(QJsonValue(QJsonObject()) != QJsonValue(true));
2333 QVERIFY(QJsonValue(QJsonObject()) != QJsonValue(1.));
2334 QVERIFY(QJsonValue(QJsonObject()) != QJsonValue(QJsonArray()));
2335
2336 QVERIFY(QJsonValue("foo") == QJsonValue(QLatin1String("foo")));
2337 QVERIFY(QJsonValue("foo") == QJsonValue(QString("foo")));
2338 QVERIFY(QJsonValue("\x66\x6f\x6f") == QJsonValue(QString("foo")));
2339 QVERIFY(QJsonValue("\x62\x61\x72") == QJsonValue("bar"));
2340 /*
2341 QVERIFY(QJsonValue(UNICODE_NON_CHARACTER) == QJsonValue(QString(UNICODE_NON_CHARACTER)));
2342 QVERIFY(QJsonValue(UNICODE_DJE) == QJsonValue(QString(UNICODE_DJE)));
2343 QVERIFY(QJsonValue("\xc3\xa9") == QJsonValue(QString("\xc3\xa9")));
2344 */
2345 }
2346
objectEquals_data()2347 void tst_QtJson::objectEquals_data()
2348 {
2349 QTest::addColumn<QJsonObject>("left");
2350 QTest::addColumn<QJsonObject>("right");
2351 QTest::addColumn<bool>("result");
2352
2353 QTest::newRow("two defaults") << QJsonObject() << QJsonObject() << true;
2354
2355 QJsonObject object1;
2356 object1.insert("property", 1);
2357 QJsonObject object2;
2358 object2["property"] = 1;
2359 QJsonObject object3;
2360 object3.insert("property1", 1);
2361 object3.insert("property2", 2);
2362
2363 QTest::newRow("the same object (1 vs 2)") << object1 << object2 << true;
2364 QTest::newRow("the same object (3 vs 3)") << object3 << object3 << true;
2365 QTest::newRow("different objects (2 vs 3)") << object2 << object3 << false;
2366 QTest::newRow("object vs default") << object1 << QJsonObject() << false;
2367
2368 QJsonObject empty;
2369 empty.insert("property", 1);
2370 empty.take("property");
2371 QTest::newRow("default vs empty") << QJsonObject() << empty << true;
2372 QTest::newRow("empty vs empty") << empty << empty << true;
2373 QTest::newRow("object vs empty") << object1 << empty << false;
2374
2375 QJsonObject referencedEmpty;
2376 referencedEmpty["undefined"];
2377 QTest::newRow("referenced empty vs referenced empty") << referencedEmpty << referencedEmpty << true;
2378 QTest::newRow("referenced empty vs object") << referencedEmpty << object1 << false;
2379
2380 QJsonObject referencedObject1;
2381 referencedObject1.insert("property", 1);
2382 referencedObject1["undefined"];
2383 QJsonObject referencedObject2;
2384 referencedObject2.insert("property", 1);
2385 referencedObject2["aaaaaaaaa"]; // earlier then "property"
2386 referencedObject2["zzzzzzzzz"]; // after "property"
2387 QTest::newRow("referenced object vs default") << referencedObject1 << QJsonObject() << false;
2388 QTest::newRow("referenced object vs referenced object") << referencedObject1 << referencedObject1 << true;
2389 QTest::newRow("referenced object vs object (different)") << referencedObject1 << object3 << false;
2390 }
2391
objectEquals()2392 void tst_QtJson::objectEquals()
2393 {
2394 QFETCH(QJsonObject, left);
2395 QFETCH(QJsonObject, right);
2396 QFETCH(bool, result);
2397
2398 QCOMPARE(left == right, result);
2399 QCOMPARE(right == left, result);
2400
2401 // invariants checks
2402 QCOMPARE(left, left);
2403 QCOMPARE(right, right);
2404 QCOMPARE(left != right, !result);
2405 QCOMPARE(right != left, !result);
2406
2407 // The same but from QJsonValue perspective
2408 QCOMPARE(QJsonValue(left) == QJsonValue(right), result);
2409 QCOMPARE(QJsonValue(left) != QJsonValue(right), !result);
2410 QCOMPARE(QJsonValue(right) == QJsonValue(left), result);
2411 QCOMPARE(QJsonValue(right) != QJsonValue(left), !result);
2412 }
2413
arrayEquals_data()2414 void tst_QtJson::arrayEquals_data()
2415 {
2416 QTest::addColumn<QJsonArray>("left");
2417 QTest::addColumn<QJsonArray>("right");
2418 QTest::addColumn<bool>("result");
2419
2420 QTest::newRow("two defaults") << QJsonArray() << QJsonArray() << true;
2421
2422 QJsonArray array1;
2423 array1.append(1);
2424 QJsonArray array2;
2425 array2.append(2111);
2426 array2[0] = 1;
2427 QJsonArray array3;
2428 array3.insert(0, 1);
2429 array3.insert(1, 2);
2430
2431 QTest::newRow("the same array (1 vs 2)") << array1 << array2 << true;
2432 QTest::newRow("the same array (3 vs 3)") << array3 << array3 << true;
2433 QTest::newRow("different arrays (2 vs 3)") << array2 << array3 << false;
2434 QTest::newRow("array vs default") << array1 << QJsonArray() << false;
2435
2436 QJsonArray empty;
2437 empty.append(1);
2438 empty.takeAt(0);
2439 QTest::newRow("default vs empty") << QJsonArray() << empty << true;
2440 QTest::newRow("empty vs default") << empty << QJsonArray() << true;
2441 QTest::newRow("empty vs empty") << empty << empty << true;
2442 QTest::newRow("array vs empty") << array1 << empty << false;
2443 }
2444
arrayEquals()2445 void tst_QtJson::arrayEquals()
2446 {
2447 QFETCH(QJsonArray, left);
2448 QFETCH(QJsonArray, right);
2449 QFETCH(bool, result);
2450
2451 QCOMPARE(left == right, result);
2452 QCOMPARE(right == left, result);
2453
2454 // invariants checks
2455 QCOMPARE(left, left);
2456 QCOMPARE(right, right);
2457 QCOMPARE(left != right, !result);
2458 QCOMPARE(right != left, !result);
2459
2460 // The same but from QJsonValue perspective
2461 QCOMPARE(QJsonValue(left) == QJsonValue(right), result);
2462 QCOMPARE(QJsonValue(left) != QJsonValue(right), !result);
2463 QCOMPARE(QJsonValue(right) == QJsonValue(left), result);
2464 QCOMPARE(QJsonValue(right) != QJsonValue(left), !result);
2465 }
2466
bom()2467 void tst_QtJson::bom()
2468 {
2469 QFile file(":/bom.json");
2470 file.open(QFile::ReadOnly);
2471 QByteArray json = file.readAll();
2472
2473 // Import json document into a QJsonDocument
2474 QJsonParseError error;
2475 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
2476
2477 QVERIFY(!doc.isNull());
2478 QVERIFY(error.error == QJsonParseError::NoError);
2479 }
2480
nesting()2481 void tst_QtJson::nesting()
2482 {
2483 // check that we abort parsing too deeply nested json documents.
2484 // this is to make sure we don't crash because the parser exhausts the
2485 // stack.
2486
2487 const char *array_data =
2488 "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["
2489 "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["
2490 "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["
2491 "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["
2492 "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["
2493 "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["
2494 "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["
2495 "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["
2496 "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
2497 "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
2498 "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
2499 "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
2500 "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
2501 "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
2502 "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
2503 "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]";
2504
2505 QByteArray json(array_data);
2506 QJsonParseError error;
2507 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
2508
2509 QVERIFY(!doc.isNull());
2510 QVERIFY(error.error == QJsonParseError::NoError);
2511
2512 json.prepend("[");
2513 json.append("]");
2514 doc = QJsonDocument::fromJson(json, &error);
2515
2516 QVERIFY(doc.isNull());
2517 QVERIFY(error.error == QJsonParseError::DeepNesting);
2518
2519 json = QByteArray("true ");
2520
2521 for (int i = 0; i < 1024; ++i) {
2522 json.prepend("{ \"Key\": ");
2523 json.append(" }");
2524 }
2525
2526 doc = QJsonDocument::fromJson(json, &error);
2527
2528 QVERIFY(!doc.isNull());
2529 QVERIFY(error.error == QJsonParseError::NoError);
2530
2531 json.prepend("[");
2532 json.append("]");
2533 doc = QJsonDocument::fromJson(json, &error);
2534
2535 QVERIFY(doc.isNull());
2536 QVERIFY(error.error == QJsonParseError::DeepNesting);
2537
2538 }
2539
longStrings()2540 void tst_QtJson::longStrings()
2541 {
2542 // test around 15 and 16 bit boundaries, as these are limits
2543 // in the data structures (for Latin1String in qjson_p.h)
2544 QString s(0x7ff0, 'a');
2545 for (int i = 0x7ff0; i < 0x8010; i++) {
2546 s.append("c");
2547
2548 QMap <QString, QVariant> map;
2549 map["key"] = s;
2550
2551 /* Create a QJsonDocument from the QMap ... */
2552 QJsonDocument d1 = QJsonDocument::fromVariant(QVariant(map));
2553 /* ... and a QByteArray from the QJsonDocument */
2554 QByteArray a1 = d1.toJson();
2555
2556 /* Create a QJsonDocument from the QByteArray ... */
2557 QJsonDocument d2 = QJsonDocument::fromJson(a1);
2558 /* ... and a QByteArray from the QJsonDocument */
2559 QByteArray a2 = d2.toJson();
2560 QVERIFY(a1 == a2);
2561 }
2562
2563 s = QString(0xfff0, 'a');
2564 for (int i = 0xfff0; i < 0x10010; i++) {
2565 s.append("c");
2566
2567 QMap <QString, QVariant> map;
2568 map["key"] = s;
2569
2570 /* Create a QJsonDocument from the QMap ... */
2571 QJsonDocument d1 = QJsonDocument::fromVariant(QVariant(map));
2572 /* ... and a QByteArray from the QJsonDocument */
2573 QByteArray a1 = d1.toJson();
2574
2575 /* Create a QJsonDocument from the QByteArray ... */
2576 QJsonDocument d2 = QJsonDocument::fromJson(a1);
2577 /* ... and a QByteArray from the QJsonDocument */
2578 QByteArray a2 = d2.toJson();
2579 QVERIFY(a1 == a2);
2580 }
2581 }
2582
testJsonValueRefDefault()2583 void tst_QtJson::testJsonValueRefDefault()
2584 {
2585 QJsonObject empty;
2586
2587 QCOMPARE(empty["n/a"].toString(), QString());
2588 QCOMPARE(empty["n/a"].toString("default"), QLatin1String("default"));
2589
2590 QCOMPARE(empty["n/a"].toBool(), false);
2591 QCOMPARE(empty["n/a"].toBool(true), true);
2592
2593 QCOMPARE(empty["n/a"].toInt(), 0);
2594 QCOMPARE(empty["n/a"].toInt(42), 42);
2595
2596 QCOMPARE(empty["n/a"].toDouble(), 0.0);
2597 QCOMPARE(empty["n/a"].toDouble(42.0), 42.0);
2598 }
2599
arrayInitializerList()2600 void tst_QtJson::arrayInitializerList()
2601 {
2602 #ifndef Q_COMPILER_INITIALIZER_LISTS
2603 QSKIP("initializer_list is enabled only with c++11 support", SkipSingle);
2604 #else
2605 QVERIFY(QJsonArray{}.isEmpty());
2606 QCOMPARE(QJsonArray{"one"}.count(), 1);
2607 QCOMPARE(QJsonArray{1}.count(), 1);
2608
2609 {
2610 QJsonArray a{1.3, "hello", 0};
2611 QCOMPARE(QJsonValue(a[0]), QJsonValue(1.3));
2612 QCOMPARE(QJsonValue(a[1]), QJsonValue("hello"));
2613 QCOMPARE(QJsonValue(a[2]), QJsonValue(0));
2614 QCOMPARE(a.count(), 3);
2615 }
2616 {
2617 QJsonObject o;
2618 o["property"] = 1;
2619 QJsonArray a1 {o};
2620 QCOMPARE(a1.count(), 1);
2621 QCOMPARE(a1[0].toObject(), o);
2622
2623 QJsonArray a2 {o, 23};
2624 QCOMPARE(a2.count(), 2);
2625 QCOMPARE(a2[0].toObject(), o);
2626 QCOMPARE(QJsonValue(a2[1]), QJsonValue(23));
2627
2628 QJsonArray a3 { a1, o, a2 };
2629 QCOMPARE(QJsonValue(a3[0]), QJsonValue(a1));
2630 QCOMPARE(QJsonValue(a3[1]), QJsonValue(o));
2631 QCOMPARE(QJsonValue(a3[2]), QJsonValue(a2));
2632
2633 QJsonArray a4 { 1, QJsonArray{1,2,3}, QJsonArray{"hello", 2}, QJsonObject{{"one", 1}} };
2634 QCOMPARE(a4.count(), 4);
2635 QCOMPARE(QJsonValue(a4[0]), QJsonValue(1));
2636
2637 {
2638 QJsonArray a41 = a4[1].toArray();
2639 QJsonArray a42 = a4[2].toArray();
2640 QJsonObject a43 = a4[3].toObject();
2641 QCOMPARE(a41.count(), 3);
2642 QCOMPARE(a42.count(), 2);
2643 QCOMPARE(a43.count(), 1);
2644
2645 QCOMPARE(QJsonValue(a41[2]), QJsonValue(3));
2646 QCOMPARE(QJsonValue(a42[1]), QJsonValue(2));
2647 QCOMPARE(QJsonValue(a43["one"]), QJsonValue(1));
2648 }
2649 }
2650 #endif
2651 }
2652
objectInitializerList()2653 void tst_QtJson::objectInitializerList()
2654 {
2655 #ifndef Q_COMPILER_INITIALIZER_LISTS
2656 QSKIP("initializer_list is enabled only with c++11 support", SkipSingle);
2657 #else
2658 QVERIFY(QJsonObject{}.isEmpty());
2659
2660 { // one property
2661 QJsonObject one {{"one", 1}};
2662 QCOMPARE(one.count(), 1);
2663 QVERIFY(one.contains("one"));
2664 QCOMPARE(QJsonValue(one["one"]), QJsonValue(1));
2665 }
2666 { // two properties
2667 QJsonObject two {
2668 {"one", 1},
2669 {"two", 2}
2670 };
2671 QCOMPARE(two.count(), 2);
2672 QVERIFY(two.contains("one"));
2673 QVERIFY(two.contains("two"));
2674 QCOMPARE(QJsonValue(two["one"]), QJsonValue(1));
2675 QCOMPARE(QJsonValue(two["two"]), QJsonValue(2));
2676 }
2677 { // nested object
2678 QJsonObject object{{"nested", QJsonObject{{"innerProperty", 2}}}};
2679 QCOMPARE(object.count(), 1);
2680 QVERIFY(object.contains("nested"));
2681 QVERIFY(object["nested"].isObject());
2682
2683 QJsonObject nested = object["nested"].toObject();
2684 QCOMPARE(QJsonValue(nested["innerProperty"]), QJsonValue(2));
2685 }
2686 { // nested array
2687 QJsonObject object{{"nested", QJsonArray{"innerValue", 2.1, "bum cyk cyk"}}};
2688 QCOMPARE(object.count(), 1);
2689 QVERIFY(object.contains("nested"));
2690 QVERIFY(object["nested"].isArray());
2691
2692 QJsonArray nested = object["nested"].toArray();
2693 QCOMPARE(nested.count(), 3);
2694 QCOMPARE(QJsonValue(nested[0]), QJsonValue("innerValue"));
2695 QCOMPARE(QJsonValue(nested[1]), QJsonValue(2.1));
2696 }
2697 #endif
2698 }
2699
unicodeKeys()2700 void tst_QtJson::unicodeKeys()
2701 {
2702 QByteArray json = "{"
2703 "\"x\\u2090_1\": \"hello_1\","
2704 "\"y\\u2090_2\": \"hello_2\","
2705 "\"T\\u2090_3\": \"hello_3\","
2706 "\"xyz_4\": \"hello_4\","
2707 "\"abc_5\": \"hello_5\""
2708 "}";
2709
2710 QJsonParseError error;
2711 QJsonDocument doc = QJsonDocument::fromJson(json, &error);
2712 QVERIFY(error.error == QJsonParseError::NoError);
2713 QJsonObject o = doc.object();
2714
2715 QCOMPARE(o.keys().size(), 5);
2716 Q_FOREACH (const QString &key, o.keys()) {
2717 QString suffix = key.mid(key.indexOf(QLatin1Char('_')));
2718 QCOMPARE(o[key].toString(), QString("hello") + suffix);
2719 }
2720 }
2721
garbageAtEnd()2722 void tst_QtJson::garbageAtEnd()
2723 {
2724 QJsonParseError error;
2725 QJsonDocument doc = QJsonDocument::fromJson("{},", &error);
2726 QVERIFY(error.error == QJsonParseError::GarbageAtEnd);
2727 QVERIFY(error.offset == 2);
2728 QVERIFY(doc.isEmpty());
2729
2730 doc = QJsonDocument::fromJson("{} ", &error);
2731 QVERIFY(error.error == QJsonParseError::NoError);
2732 QVERIFY(!doc.isEmpty());
2733 }
2734
2735 QTEST_MAIN(tst_QtJson)
2736 #include "tst_qtjson.moc"
2737