1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
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 The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include <qjsonobject.h>
41#include <qjsonvalue.h>
42#include <qjsonarray.h>
43#include <qstringlist.h>
44#include <qdebug.h>
45#include <qvariant.h>
46#include "qjson_p.h"
47#include "qjsonwriter_p.h"
48
49QT_BEGIN_NAMESPACE
50
51/*!
52 \class QJsonObject
53 \inmodule QtCore
54 \ingroup json
55 \ingroup shared
56 \reentrant
57 \since 5.0
58
59 \brief The QJsonObject class encapsulates a JSON object.
60
61 A JSON object is a list of key value pairs, where the keys are unique strings
62 and the values are represented by a QJsonValue.
63
64 A QJsonObject can be converted to and from a QVariantMap. You can query the
65 number of (key, value) pairs with size(), insert(), and remove() entries from it
66 and iterate over its content using the standard C++ iterator pattern.
67
68 QJsonObject is an implicitly shared class, and shares the data with the document
69 it has been created from as long as it is not being modified.
70
71 You can convert the object to and from text based JSON through QJsonDocument.
72
73 \sa {JSON Support in Qt}, {JSON Save Game Example}
74*/
75
76/*!
77 \typedef QJsonObject::Iterator
78
79 Qt-style synonym for QJsonObject::iterator.
80*/
81
82/*!
83 \typedef QJsonObject::ConstIterator
84
85 Qt-style synonym for QJsonObject::const_iterator.
86*/
87
88/*!
89 \typedef QJsonObject::key_type
90
91 Typedef for QString. Provided for STL compatibility.
92*/
93
94/*!
95 \typedef QJsonObject::mapped_type
96
97 Typedef for QJsonValue. Provided for STL compatibility.
98*/
99
100/*!
101 \typedef QJsonObject::size_type
102
103 Typedef for int. Provided for STL compatibility.
104*/
105
106
107/*!
108 Constructs an empty JSON object.
109
110 \sa isEmpty()
111 */
112QJsonObject::QJsonObject()
113 : d(nullptr), o(nullptr)
114{
115}
116
117/*!
118 \fn QJsonObject::QJsonObject(std::initializer_list<QPair<QString, QJsonValue> > args)
119 \since 5.4
120 Constructs a QJsonObject instance initialized from \a args initialization list.
121 For example:
122 \code
123 QJsonObject object
124 {
125 {"property1", 1},
126 {"property2", 2}
127 };
128 \endcode
129*/
130
131/*!
132 \internal
133 */
134QJsonObject::QJsonObject(QJsonPrivate::Data *data, QJsonPrivate::Object *object)
135 : d(data), o(object)
136{
137 Q_ASSERT(d);
138 Q_ASSERT(o);
139 d->ref.ref();
140}
141
142/*!
143 This method replaces part of the QJsonObject(std::initializer_list<QPair<QString, QJsonValue>> args) body.
144 The constructor needs to be inline, but we do not want to leak implementation details
145 of this class.
146 \note this method is called for an uninitialized object
147 \internal
148 */
149
150void QJsonObject::initialize()
151{
152 d = nullptr;
153 o = nullptr;
154}
155
156/*!
157 Destroys the object.
158 */
159QJsonObject::~QJsonObject()
160{
161 if (d && !d->ref.deref())
162 delete d;
163}
164
165/*!
166 Creates a copy of \a other.
167
168 Since QJsonObject is implicitly shared, the copy is shallow
169 as long as the object does not get modified.
170 */
171QJsonObject::QJsonObject(const QJsonObject &other)
172{
173 d = other.d;
174 o = other.o;
175 if (d)
176 d->ref.ref();
177}
178
179/*!
180 Assigns \a other to this object.
181 */
182QJsonObject &QJsonObject::operator =(const QJsonObject &other)
183{
184 if (d != other.d) {
185 if (d && !d->ref.deref())
186 delete d;
187 d = other.d;
188 if (d)
189 d->ref.ref();
190 }
191 o = other.o;
192
193 return *this;
194}
195
196/*!
197 \fn QJsonObject::QJsonObject(QJsonObject &&other)
198 \since 5.10
199
200 Move-constructs a QJsonObject from \a other.
201*/
202
203/*!
204 \fn QJsonObject &QJsonObject::operator =(QJsonObject &&other)
205 \since 5.10
206
207 Move-assigns \a other to this object.
208*/
209
210/*!
211 \fn void QJsonObject::swap(QJsonObject &other)
212 \since 5.10
213
214 Swaps the object \a other with this. This operation is very fast and never fails.
215*/
216
217
218/*!
219 Converts the variant map \a map to a QJsonObject.
220
221 The keys in \a map will be used as the keys in the JSON object,
222 and the QVariant values will be converted to JSON values.
223
224 \sa fromVariantHash(), toVariantMap(), QJsonValue::fromVariant()
225 */
226QJsonObject QJsonObject::fromVariantMap(const QVariantMap &map)
227{
228 QJsonObject object;
229 if (map.isEmpty())
230 return object;
231
232 object.detach2(1024);
233
234 QVector<QJsonPrivate::offset> offsets;
235 QJsonPrivate::offset currentOffset;
236 currentOffset = sizeof(QJsonPrivate::Base);
237
238 // the map is already sorted, so we can simply append one entry after the other and
239 // write the offset table at the end
240 for (QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it) {
241 QString key = it.key();
242 QJsonValue val = QJsonValue::fromVariant(it.value());
243
244 bool latinOrIntValue;
245 int valueSize = QJsonPrivate::Value::requiredStorage(val, &latinOrIntValue);
246
247 bool latinKey = QJsonPrivate::useCompressed(key);
248 int valueOffset = sizeof(QJsonPrivate::Entry) + QJsonPrivate::qStringSize(key, latinKey);
249 int requiredSize = valueOffset + valueSize;
250
251 if (!object.detach2(requiredSize + sizeof(QJsonPrivate::offset))) // offset for the new index entry
252 return QJsonObject();
253
254 QJsonPrivate::Entry *e = reinterpret_cast<QJsonPrivate::Entry *>(reinterpret_cast<char *>(object.o) + currentOffset);
255 e->value.type = val.t;
256 e->value.latinKey = latinKey;
257 e->value.latinOrIntValue = latinOrIntValue;
258 e->value.value = QJsonPrivate::Value::valueToStore(val, (char *)e - (char *)object.o + valueOffset);
259 QJsonPrivate::copyString((char *)(e + 1), key, latinKey);
260 if (valueSize)
261 QJsonPrivate::Value::copyData(val, (char *)e + valueOffset, latinOrIntValue);
262
263 offsets << currentOffset;
264 currentOffset += requiredSize;
265 object.o->size = currentOffset;
266 }
267
268 // write table
269 object.o->tableOffset = currentOffset;
270 if (!object.detach2(sizeof(QJsonPrivate::offset)*offsets.size()))
271 return QJsonObject();
272 memcpy(object.o->table(), offsets.constData(), offsets.size()*sizeof(uint));
273 object.o->length = offsets.size();
274 object.o->size = currentOffset + sizeof(QJsonPrivate::offset)*offsets.size();
275
276 return object;
277}
278
279/*!
280 Converts this object to a QVariantMap.
281
282 Returns the created map.
283
284 \sa toVariantHash()
285 */
286QVariantMap QJsonObject::toVariantMap() const
287{
288 QVariantMap map;
289 if (o) {
290 for (uint i = 0; i < o->length; ++i) {
291 QJsonPrivate::Entry *e = o->entryAt(i);
292 map.insert(e->key(), QJsonValue(d, o, e->value).toVariant());
293 }
294 }
295 return map;
296}
297
298/*!
299 Converts the variant hash \a hash to a QJsonObject.
300 \since 5.5
301
302 The keys in \a hash will be used as the keys in the JSON object,
303 and the QVariant values will be converted to JSON values.
304
305 \sa fromVariantMap(), toVariantHash(), QJsonValue::fromVariant()
306 */
307QJsonObject QJsonObject::fromVariantHash(const QVariantHash &hash)
308{
309 // ### this is implemented the trivial way, not the most efficient way
310
311 QJsonObject object;
312 for (QVariantHash::const_iterator it = hash.constBegin(); it != hash.constEnd(); ++it)
313 object.insert(it.key(), QJsonValue::fromVariant(it.value()));
314 return object;
315}
316
317/*!
318 Converts this object to a QVariantHash.
319 \since 5.5
320
321 Returns the created hash.
322
323 \sa toVariantMap()
324 */
325QVariantHash QJsonObject::toVariantHash() const
326{
327 QVariantHash hash;
328 if (o) {
329 hash.reserve(o->length);
330 for (uint i = 0; i < o->length; ++i) {
331 QJsonPrivate::Entry *e = o->entryAt(i);
332 hash.insert(e->key(), QJsonValue(d, o, e->value).toVariant());
333 }
334 }
335 return hash;
336}
337
338/*!
339 Returns a list of all keys in this object.
340
341 The list is sorted lexographically.
342 */
343QStringList QJsonObject::keys() const
344{
345 QStringList keys;
346 if (o) {
347 keys.reserve(o->length);
348 for (uint i = 0; i < o->length; ++i) {
349 QJsonPrivate::Entry *e = o->entryAt(i);
350 keys.append(e->key());
351 }
352 }
353 return keys;
354}
355
356/*!
357 Returns the number of (key, value) pairs stored in the object.
358 */
359int QJsonObject::size() const
360{
361 if (!d)
362 return 0;
363
364 return o->length;
365}
366
367/*!
368 Returns \c true if the object is empty. This is the same as size() == 0.
369
370 \sa size()
371 */
372bool QJsonObject::isEmpty() const
373{
374 if (!d)
375 return true;
376
377 return !o->length;
378}
379
380#if QT_STRINGVIEW_LEVEL < 2
381/*!
382 Returns a QJsonValue representing the value for the key \a key.
383
384 The returned QJsonValue is QJsonValue::Undefined if the key does not exist.
385
386 \sa QJsonValue, QJsonValue::isUndefined()
387 */
388QJsonValue QJsonObject::value(const QString &key) const
389{
390 return value(QStringView(key));
391}
392#endif
393
394/*!
395 \overload
396 \since 5.14
397*/
398QJsonValue QJsonObject::value(QStringView key) const
399{
400 return valueImpl(key);
401}
402
403/*!
404 \overload
405 \since 5.7
406*/
407QJsonValue QJsonObject::value(QLatin1String key) const
408{
409 return valueImpl(key);
410}
411
412/*!
413 \internal
414*/
415template <typename T>
416QJsonValue QJsonObject::valueImpl(T key) const
417{
418 if (!d)
419 return QJsonValue(QJsonValue::Undefined);
420
421 bool keyExists;
422 int i = o->indexOf(key, &keyExists);
423 if (!keyExists)
424 return QJsonValue(QJsonValue::Undefined);
425 return QJsonValue(d, o, o->entryAt(i)->value);
426}
427
428#if QT_STRINGVIEW_LEVEL < 2
429/*!
430 Returns a QJsonValue representing the value for the key \a key.
431
432 This does the same as value().
433
434 The returned QJsonValue is QJsonValue::Undefined if the key does not exist.
435
436 \sa value(), QJsonValue, QJsonValue::isUndefined()
437 */
438QJsonValue QJsonObject::operator [](const QString &key) const
439{
440 return (*this)[QStringView(key)];
441}
442#endif
443
444/*!
445 \fn QJsonValue QJsonObject::operator [](QStringView key) const
446
447 \overload
448 \since 5.14
449*/
450
451/*!
452 \fn QJsonValue QJsonObject::operator [](QLatin1String key) const
453
454 \overload
455 \since 5.7
456*/
457
458#if QT_STRINGVIEW_LEVEL < 2
459/*!
460 Returns a reference to the value for \a key.
461
462 The return value is of type QJsonValueRef, a helper class for QJsonArray
463 and QJsonObject. When you get an object of type QJsonValueRef, you can
464 use it as if it were a reference to a QJsonValue. If you assign to it,
465 the assignment will apply to the element in the QJsonArray or QJsonObject
466 from which you got the reference.
467
468 \sa value()
469 */
470QJsonValueRef QJsonObject::operator [](const QString &key)
471{
472 return (*this)[QStringView(key)];
473}
474#endif
475
476/*!
477 \overload
478 \since 5.14
479*/
480QJsonValueRef QJsonObject::operator [](QStringView key)
481{
482 return atImpl(key);
483}
484
485/*!
486 \overload
487 \since 5.7
488*/
489QJsonValueRef QJsonObject::operator [](QLatin1String key)
490{
491 return atImpl(key);
492}
493
494/*!
495 \internal
496*/
497template <typename T>
498QJsonValueRef QJsonObject::atImpl(T key)
499{
500 bool keyExists = false;
501 int index = o ? o->indexOf(key, &keyExists) : 0;
502 if (!keyExists) {
503 iterator i = insertAt(index, key, QJsonValue(), false);
504 index = i.i;
505 }
506 return QJsonValueRef(this, index);
507}
508
509#if QT_STRINGVIEW_LEVEL < 2
510/*!
511 Inserts a new item with the key \a key and a value of \a value.
512
513 If there is already an item with the key \a key, then that item's value
514 is replaced with \a value.
515
516 Returns an iterator pointing to the inserted item.
517
518 If the value is QJsonValue::Undefined, it will cause the key to get removed
519 from the object. The returned iterator will then point to end().
520
521 \sa remove(), take(), QJsonObject::iterator, end()
522 */
523QJsonObject::iterator QJsonObject::insert(const QString &key, const QJsonValue &value)
524{
525 return insert(QStringView(key), value);
526}
527#endif
528
529/*!
530 \overload
531 \since 5.14
532*/
533QJsonObject::iterator QJsonObject::insert(QStringView key, const QJsonValue &value)
534{
535 return insertImpl(key, value);
536}
537
538/*!
539 \overload
540 \since 5.14
541*/
542QJsonObject::iterator QJsonObject::insert(QLatin1String key, const QJsonValue &value)
543{
544 return insertImpl(key, value);
545}
546
547/*!
548 \internal
549*/
550template <typename T>
551QJsonObject::iterator QJsonObject::insertImpl(T key, const QJsonValue &value)
552{
553 if (value.t == QJsonValue::Undefined) {
554 remove(key);
555 return end();
556 }
557 bool keyExists = false;
558 int pos = o ? o->indexOf(key, &keyExists) : 0;
559 return insertAt(pos, key, value, keyExists);
560}
561
562/*!
563 \internal
564 */
565template <typename T>
566QJsonObject::iterator QJsonObject::insertAt(int pos, T key, const QJsonValue &value, bool keyExists)
567{
568 QJsonValue val = value;
569
570 bool latinOrIntValue;
571 int valueSize = QJsonPrivate::Value::requiredStorage(val, &latinOrIntValue);
572
573 bool latinKey = QJsonPrivate::useCompressed(key);
574 int valueOffset = sizeof(QJsonPrivate::Entry) + QJsonPrivate::qStringSize(key, latinKey);
575 int requiredSize = valueOffset + valueSize;
576
577 if (!detach2(requiredSize + sizeof(QJsonPrivate::offset))) // offset for the new index entry
578 return iterator();
579
580 if (!o->length)
581 o->tableOffset = sizeof(QJsonPrivate::Object);
582
583 if (keyExists)
584 ++d->compactionCounter;
585
586 uint off = o->reserveSpace(requiredSize, pos, 1, keyExists);
587 if (!off)
588 return end();
589
590 QJsonPrivate::Entry *e = o->entryAt(pos);
591 e->value.type = val.t;
592 e->value.latinKey = latinKey;
593 e->value.latinOrIntValue = latinOrIntValue;
594 e->value.value = QJsonPrivate::Value::valueToStore(val, (char *)e - (char *)o + valueOffset);
595 QJsonPrivate::copyString((char *)(e + 1), key, latinKey);
596 if (valueSize)
597 QJsonPrivate::Value::copyData(val, (char *)e + valueOffset, latinOrIntValue);
598
599 compactIfNeeded();
600
601 return iterator(this, pos);
602}
603
604#if QT_STRINGVIEW_LEVEL < 2
605/*!
606 Removes \a key from the object.
607
608 \sa insert(), take()
609 */
610void QJsonObject::remove(const QString &key)
611{
612 remove(QStringView(key));
613}
614#endif
615
616/*!
617 \overload
618 \since 5.14
619*/
620void QJsonObject::remove(QStringView key)
621{
622 removeImpl(key);
623}
624
625/*!
626 \overload
627 \since 5.14
628*/
629void QJsonObject::remove(QLatin1String key)
630{
631 removeImpl(key);
632}
633
634/*!
635 \internal
636*/
637template <typename T>
638void QJsonObject::removeImpl(T key)
639{
640 if (!d)
641 return;
642
643 bool keyExists;
644 int index = o->indexOf(key, &keyExists);
645 if (!keyExists)
646 return;
647
648 removeAt(index);
649}
650
651#if QT_STRINGVIEW_LEVEL < 2
652/*!
653 Removes \a key from the object.
654
655 Returns a QJsonValue containing the value referenced by \a key.
656 If \a key was not contained in the object, the returned QJsonValue
657 is QJsonValue::Undefined.
658
659 \sa insert(), remove(), QJsonValue
660 */
661QJsonValue QJsonObject::take(const QString &key)
662{
663 return take(QStringView(key));
664}
665#endif
666
667/*!
668 \overload
669 \since 5.14
670*/
671QJsonValue QJsonObject::take(QStringView key)
672{
673 return takeImpl(key);
674}
675
676/*!
677 \overload
678 \since 5.14
679*/
680QJsonValue QJsonObject::take(QLatin1String key)
681{
682 return takeImpl(key);
683}
684
685/*!
686 \internal
687*/
688template <typename T>
689QJsonValue QJsonObject::takeImpl(T key)
690{
691 if (!o)
692 return QJsonValue(QJsonValue::Undefined);
693
694 bool keyExists;
695 int index = o->indexOf(key, &keyExists);
696 if (!keyExists)
697 return QJsonValue(QJsonValue::Undefined);
698
699 QJsonValue v(d, o, o->entryAt(index)->value);
700 removeAt(index);
701
702 return v;
703}
704
705#if QT_STRINGVIEW_LEVEL < 2
706/*!
707 Returns \c true if the object contains key \a key.
708
709 \sa insert(), remove(), take()
710 */
711bool QJsonObject::contains(const QString &key) const
712{
713 return contains(QStringView(key));
714}
715#endif
716
717/*!
718 \overload
719 \since 5.14
720*/
721bool QJsonObject::contains(QStringView key) const
722{
723 return containsImpl(key);
724}
725
726/*!
727 \overload
728 \since 5.7
729*/
730bool QJsonObject::contains(QLatin1String key) const
731{
732 return containsImpl(key);
733}
734
735/*!
736 \internal
737*/
738template <typename T>
739bool QJsonObject::containsImpl(T key) const
740{
741 if (!o)
742 return false;
743
744 bool keyExists;
745 o->indexOf(key, &keyExists);
746 return keyExists;
747}
748
749/*!
750 Returns \c true if \a other is equal to this object.
751 */
752bool QJsonObject::operator==(const QJsonObject &other) const
753{
754 if (o == other.o)
755 return true;
756
757 if (!o)
758 return !other.o->length;
759 if (!other.o)
760 return !o->length;
761 if (o->length != other.o->length)
762 return false;
763
764 for (uint i = 0; i < o->length; ++i) {
765 QJsonPrivate::Entry *e = o->entryAt(i);
766 QJsonValue v(d, o, e->value);
767 if (other.value(e->key()) != v)
768 return false;
769 }
770
771 return true;
772}
773
774/*!
775 Returns \c true if \a other is not equal to this object.
776 */
777bool QJsonObject::operator!=(const QJsonObject &other) const
778{
779 return !(*this == other);
780}
781
782/*!
783 Removes the (key, value) pair pointed to by the iterator \a it
784 from the map, and returns an iterator to the next item in the
785 map.
786
787 \sa remove()
788 */
789QJsonObject::iterator QJsonObject::erase(QJsonObject::iterator it)
790{
791 Q_ASSERT(d && d->ref.loadRelaxed() == 1);
792 if (it.o != this || it.i < 0 || it.i >= (int)o->length)
793 return iterator(this, o->length);
794
795 int index = it.i;
796
797 removeAt(index);
798
799 // iterator hasn't changed
800 return it;
801}
802
803#if QT_STRINGVIEW_LEVEL < 2
804/*!
805 Returns an iterator pointing to the item with key \a key in the
806 map.
807
808 If the map contains no item with key \a key, the function
809 returns end().
810 */
811QJsonObject::iterator QJsonObject::find(const QString &key)
812{
813 return find(QStringView(key));
814}
815#endif
816
817/*!
818 \overload
819 \since 5.14
820*/
821QJsonObject::iterator QJsonObject::find(QStringView key)
822{
823 return findImpl(key);
824}
825
826/*!
827 \overload
828 \since 5.7
829*/
830QJsonObject::iterator QJsonObject::find(QLatin1String key)
831{
832 return findImpl(key);
833}
834
835/*!
836 \internal
837*/
838template <typename T>
839QJsonObject::iterator QJsonObject::findImpl(T key)
840{
841 bool keyExists = false;
842 int index = o ? o->indexOf(key, &keyExists) : 0;
843 if (!keyExists)
844 return end();
845 detach2();
846 return iterator(this, index);
847}
848
849#if QT_STRINGVIEW_LEVEL < 2
850/*! \fn QJsonObject::const_iterator QJsonObject::find(const QString &key) const
851
852 \overload
853*/
854#endif
855
856/*! \fn QJsonObject::const_iterator QJsonObject::find(QStringView key) const
857
858 \overload
859 \since 5.14
860*/
861
862/*! \fn QJsonObject::const_iterator QJsonObject::find(QLatin1String key) const
863
864 \overload
865 \since 5.7
866*/
867
868#if QT_STRINGVIEW_LEVEL < 2
869/*!
870 Returns a const iterator pointing to the item with key \a key in the
871 map.
872
873 If the map contains no item with key \a key, the function
874 returns constEnd().
875 */
876QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const
877{
878 return constFind(QStringView(key));
879}
880#endif
881
882/*!
883 \overload
884 \since 5.14
885*/
886QJsonObject::const_iterator QJsonObject::constFind(QStringView key) const
887{
888 return constFindImpl(key);
889}
890
891/*!
892 \overload
893 \since 5.7
894*/
895QJsonObject::const_iterator QJsonObject::constFind(QLatin1String key) const
896{
897 return constFindImpl(key);
898}
899
900/*!
901 \internal
902*/
903template <typename T>
904QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
905{
906 bool keyExists = false;
907 int index = o ? o->indexOf(key, &keyExists) : 0;
908 if (!keyExists)
909 return end();
910 return const_iterator(this, index);
911}
912
913/*! \fn int QJsonObject::count() const
914
915 \overload
916
917 Same as size().
918*/
919
920/*! \fn int QJsonObject::length() const
921
922 \overload
923
924 Same as size().
925*/
926
927/*! \fn QJsonObject::iterator QJsonObject::begin()
928
929 Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in
930 the object.
931
932 \sa constBegin(), end()
933*/
934
935/*! \fn QJsonObject::const_iterator QJsonObject::begin() const
936
937 \overload
938*/
939
940/*! \fn QJsonObject::const_iterator QJsonObject::constBegin() const
941
942 Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item
943 in the object.
944
945 \sa begin(), constEnd()
946*/
947
948/*! \fn QJsonObject::iterator QJsonObject::end()
949
950 Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item
951 after the last item in the object.
952
953 \sa begin(), constEnd()
954*/
955
956/*! \fn QJsonObject::const_iterator QJsonObject::end() const
957
958 \overload
959*/
960
961/*! \fn QJsonObject::const_iterator QJsonObject::constEnd() const
962
963 Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
964 item after the last item in the object.
965
966 \sa constBegin(), end()
967*/
968
969/*!
970 \fn bool QJsonObject::empty() const
971
972 This function is provided for STL compatibility. It is equivalent
973 to isEmpty(), returning \c true if the object is empty; otherwise
974 returning \c false.
975*/
976
977/*! \class QJsonObject::iterator
978 \inmodule QtCore
979 \ingroup json
980 \reentrant
981 \since 5.0
982
983 \brief The QJsonObject::iterator class provides an STL-style non-const iterator for QJsonObject.
984
985 QJsonObject::iterator allows you to iterate over a QJsonObject
986 and to modify the value (but not the key) stored under
987 a particular key. If you want to iterate over a const QJsonObject, you
988 should use QJsonObject::const_iterator. It is generally good practice to
989 use QJsonObject::const_iterator on a non-const QJsonObject as well, unless you
990 need to change the QJsonObject through the iterator. Const iterators are
991 slightly faster, and improve code readability.
992
993 The default QJsonObject::iterator constructor creates an uninitialized
994 iterator. You must initialize it using a QJsonObject function like
995 QJsonObject::begin(), QJsonObject::end(), or QJsonObject::find() before you can
996 start iterating.
997
998 Multiple iterators can be used on the same object. Existing iterators will however
999 become dangling once the object gets modified.
1000
1001 \sa QJsonObject::const_iterator, {JSON Support in Qt}, {JSON Save Game Example}
1002*/
1003
1004/*! \typedef QJsonObject::iterator::difference_type
1005
1006 \internal
1007*/
1008
1009/*! \typedef QJsonObject::iterator::iterator_category
1010
1011 A synonym for \e {std::random_access_iterator_tag} indicating
1012 this iterator is a random-access iterator.
1013
1014 \note In Qt versions before 5.6, this was set by mistake to
1015 \e {std::bidirectional_iterator_tag}.
1016*/
1017
1018/*! \typedef QJsonObject::iterator::reference
1019
1020 \internal
1021*/
1022
1023/*! \typedef QJsonObject::iterator::value_type
1024
1025 \internal
1026*/
1027
1028/*! \typedef QJsonObject::iterator::pointer
1029
1030 \internal
1031*/
1032
1033/*! \fn QJsonObject::iterator::iterator()
1034
1035 Constructs an uninitialized iterator.
1036
1037 Functions like key(), value(), and operator++() must not be
1038 called on an uninitialized iterator. Use operator=() to assign a
1039 value to it before using it.
1040
1041 \sa QJsonObject::begin(), QJsonObject::end()
1042*/
1043
1044/*! \fn QJsonObject::iterator::iterator(QJsonObject *obj, int index)
1045 \internal
1046*/
1047
1048/*! \fn QString QJsonObject::iterator::key() const
1049
1050 Returns the current item's key.
1051
1052 There is no direct way of changing an item's key through an
1053 iterator, although it can be done by calling QJsonObject::erase()
1054 followed by QJsonObject::insert().
1055
1056 \sa value()
1057*/
1058
1059/*! \fn QJsonValueRef QJsonObject::iterator::value() const
1060
1061 Returns a modifiable reference to the current item's value.
1062
1063 You can change the value of an item by using value() on
1064 the left side of an assignment.
1065
1066 The return value is of type QJsonValueRef, a helper class for QJsonArray
1067 and QJsonObject. When you get an object of type QJsonValueRef, you can
1068 use it as if it were a reference to a QJsonValue. If you assign to it,
1069 the assignment will apply to the element in the QJsonArray or QJsonObject
1070 from which you got the reference.
1071
1072 \sa key(), operator*()
1073*/
1074
1075/*! \fn QJsonValueRef QJsonObject::iterator::operator*() const
1076
1077 Returns a modifiable reference to the current item's value.
1078
1079 Same as value().
1080
1081 The return value is of type QJsonValueRef, a helper class for QJsonArray
1082 and QJsonObject. When you get an object of type QJsonValueRef, you can
1083 use it as if it were a reference to a QJsonValue. If you assign to it,
1084 the assignment will apply to the element in the QJsonArray or QJsonObject
1085 from which you got the reference.
1086
1087 \sa key()
1088*/
1089
1090/*! \fn QJsonValueRef *QJsonObject::iterator::operator->() const
1091
1092 Returns a pointer to a modifiable reference to the current item.
1093*/
1094
1095/*!
1096 \fn bool QJsonObject::iterator::operator==(const iterator &other) const
1097 \fn bool QJsonObject::iterator::operator==(const const_iterator &other) const
1098
1099 Returns \c true if \a other points to the same item as this
1100 iterator; otherwise returns \c false.
1101
1102 \sa operator!=()
1103*/
1104
1105/*!
1106 \fn bool QJsonObject::iterator::operator!=(const iterator &other) const
1107 \fn bool QJsonObject::iterator::operator!=(const const_iterator &other) const
1108
1109 Returns \c true if \a other points to a different item than this
1110 iterator; otherwise returns \c false.
1111
1112 \sa operator==()
1113*/
1114
1115/*! \fn QJsonObject::iterator QJsonObject::iterator::operator++()
1116
1117 The prefix ++ operator, \c{++i}, advances the iterator to the
1118 next item in the object and returns an iterator to the new current
1119 item.
1120
1121 Calling this function on QJsonObject::end() leads to undefined results.
1122
1123 \sa operator--()
1124*/
1125
1126/*! \fn QJsonObject::iterator QJsonObject::iterator::operator++(int)
1127
1128 \overload
1129
1130 The postfix ++ operator, \c{i++}, advances the iterator to the
1131 next item in the object and returns an iterator to the previously
1132 current item.
1133*/
1134
1135/*! \fn QJsonObject::iterator QJsonObject::iterator::operator--()
1136
1137 The prefix -- operator, \c{--i}, makes the preceding item
1138 current and returns an iterator pointing to the new current item.
1139
1140 Calling this function on QJsonObject::begin() leads to undefined
1141 results.
1142
1143 \sa operator++()
1144*/
1145
1146/*! \fn QJsonObject::iterator QJsonObject::iterator::operator--(int)
1147
1148 \overload
1149
1150 The postfix -- operator, \c{i--}, makes the preceding item
1151 current and returns an iterator pointing to the previously
1152 current item.
1153*/
1154
1155/*! \fn QJsonObject::iterator QJsonObject::iterator::operator+(int j) const
1156
1157 Returns an iterator to the item at \a j positions forward from
1158 this iterator. If \a j is negative, the iterator goes backward.
1159
1160 \sa operator-()
1161
1162*/
1163
1164/*! \fn QJsonObject::iterator QJsonObject::iterator::operator-(int j) const
1165
1166 Returns an iterator to the item at \a j positions backward from
1167 this iterator. If \a j is negative, the iterator goes forward.
1168
1169 \sa operator+()
1170*/
1171
1172/*! \fn QJsonObject::iterator &QJsonObject::iterator::operator+=(int j)
1173
1174 Advances the iterator by \a j items. If \a j is negative, the
1175 iterator goes backward.
1176
1177 \sa operator-=(), operator+()
1178*/
1179
1180/*! \fn QJsonObject::iterator &QJsonObject::iterator::operator-=(int j)
1181
1182 Makes the iterator go back by \a j items. If \a j is negative,
1183 the iterator goes forward.
1184
1185 \sa operator+=(), operator-()
1186*/
1187
1188/*!
1189 \class QJsonObject::const_iterator
1190 \inmodule QtCore
1191 \ingroup json
1192 \since 5.0
1193 \brief The QJsonObject::const_iterator class provides an STL-style const iterator for QJsonObject.
1194
1195 QJsonObject::const_iterator allows you to iterate over a QJsonObject.
1196 If you want to modify the QJsonObject as you iterate
1197 over it, you must use QJsonObject::iterator instead. It is generally
1198 good practice to use QJsonObject::const_iterator on a non-const QJsonObject as
1199 well, unless you need to change the QJsonObject through the iterator.
1200 Const iterators are slightly faster and improve code
1201 readability.
1202
1203 The default QJsonObject::const_iterator constructor creates an
1204 uninitialized iterator. You must initialize it using a QJsonObject
1205 function like QJsonObject::constBegin(), QJsonObject::constEnd(), or
1206 QJsonObject::find() before you can start iterating.
1207
1208 Multiple iterators can be used on the same object. Existing iterators
1209 will however become dangling if the object gets modified.
1210
1211 \sa QJsonObject::iterator, {JSON Support in Qt}, {JSON Save Game Example}
1212*/
1213
1214/*! \typedef QJsonObject::const_iterator::difference_type
1215
1216 \internal
1217*/
1218
1219/*! \typedef QJsonObject::const_iterator::iterator_category
1220
1221 A synonym for \e {std::random_access_iterator_tag} indicating
1222 this iterator is a random-access iterator.
1223
1224 \note In Qt versions before 5.6, this was set by mistake to
1225 \e {std::bidirectional_iterator_tag}.
1226*/
1227
1228/*! \typedef QJsonObject::const_iterator::reference
1229
1230 \internal
1231*/
1232
1233/*! \typedef QJsonObject::const_iterator::value_type
1234
1235 \internal
1236*/
1237
1238/*! \typedef QJsonObject::const_iterator::pointer
1239
1240 \internal
1241*/
1242
1243/*! \fn QJsonObject::const_iterator::const_iterator()
1244
1245 Constructs an uninitialized iterator.
1246
1247 Functions like key(), value(), and operator++() must not be
1248 called on an uninitialized iterator. Use operator=() to assign a
1249 value to it before using it.
1250
1251 \sa QJsonObject::constBegin(), QJsonObject::constEnd()
1252*/
1253
1254/*! \fn QJsonObject::const_iterator::const_iterator(const QJsonObject *obj, int index)
1255 \internal
1256*/
1257
1258/*! \fn QJsonObject::const_iterator::const_iterator(const iterator &other)
1259
1260 Constructs a copy of \a other.
1261*/
1262
1263/*! \fn QString QJsonObject::const_iterator::key() const
1264
1265 Returns the current item's key.
1266
1267 \sa value()
1268*/
1269
1270/*! \fn QJsonValue QJsonObject::const_iterator::value() const
1271
1272 Returns the current item's value.
1273
1274 \sa key(), operator*()
1275*/
1276
1277/*! \fn QJsonValue QJsonObject::const_iterator::operator*() const
1278
1279 Returns the current item's value.
1280
1281 Same as value().
1282
1283 \sa key()
1284*/
1285
1286/*! \fn QJsonValue *QJsonObject::const_iterator::operator->() const
1287
1288 Returns a pointer to the current item.
1289*/
1290
1291/*! \fn bool QJsonObject::const_iterator::operator==(const const_iterator &other) const
1292 \fn bool QJsonObject::const_iterator::operator==(const iterator &other) const
1293
1294 Returns \c true if \a other points to the same item as this
1295 iterator; otherwise returns \c false.
1296
1297 \sa operator!=()
1298*/
1299
1300/*! \fn bool QJsonObject::const_iterator::operator!=(const const_iterator &other) const
1301 \fn bool QJsonObject::const_iterator::operator!=(const iterator &other) const
1302
1303 Returns \c true if \a other points to a different item than this
1304 iterator; otherwise returns \c false.
1305
1306 \sa operator==()
1307*/
1308
1309/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator++()
1310
1311 The prefix ++ operator, \c{++i}, advances the iterator to the
1312 next item in the object and returns an iterator to the new current
1313 item.
1314
1315 Calling this function on QJsonObject::end() leads to undefined results.
1316
1317 \sa operator--()
1318*/
1319
1320/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator++(int)
1321
1322 \overload
1323
1324 The postfix ++ operator, \c{i++}, advances the iterator to the
1325 next item in the object and returns an iterator to the previously
1326 current item.
1327*/
1328
1329/*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator--()
1330
1331 The prefix -- operator, \c{--i}, makes the preceding item
1332 current and returns an iterator pointing to the new current item.
1333
1334 Calling this function on QJsonObject::begin() leads to undefined
1335 results.
1336
1337 \sa operator++()
1338*/
1339
1340/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator--(int)
1341
1342 \overload
1343
1344 The postfix -- operator, \c{i--}, makes the preceding item
1345 current and returns an iterator pointing to the previously
1346 current item.
1347*/
1348
1349/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator+(int j) const
1350
1351 Returns an iterator to the item at \a j positions forward from
1352 this iterator. If \a j is negative, the iterator goes backward.
1353
1354 This operation can be slow for large \a j values.
1355
1356 \sa operator-()
1357*/
1358
1359/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator-(int j) const
1360
1361 Returns an iterator to the item at \a j positions backward from
1362 this iterator. If \a j is negative, the iterator goes forward.
1363
1364 This operation can be slow for large \a j values.
1365
1366 \sa operator+()
1367*/
1368
1369/*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator+=(int j)
1370
1371 Advances the iterator by \a j items. If \a j is negative, the
1372 iterator goes backward.
1373
1374 This operation can be slow for large \a j values.
1375
1376 \sa operator-=(), operator+()
1377*/
1378
1379/*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator-=(int j)
1380
1381 Makes the iterator go back by \a j items. If \a j is negative,
1382 the iterator goes forward.
1383
1384 This operation can be slow for large \a j values.
1385
1386 \sa operator+=(), operator-()
1387*/
1388
1389
1390/*!
1391 \internal
1392 */
1393void QJsonObject::detach(uint reserve)
1394{
1395 Q_UNUSED(reserve)
1396 Q_ASSERT(!reserve);
1397 detach2(reserve);
1398}
1399
1400bool QJsonObject::detach2(uint reserve)
1401{
1402 if (!d) {
1403 if (reserve >= QJsonPrivate::Value::MaxSize) {
1404 qWarning("QJson: Document too large to store in data structure");
1405 return false;
1406 }
1407 d = new QJsonPrivate::Data(reserve, QJsonValue::Object);
1408 o = static_cast<QJsonPrivate::Object *>(d->header->root());
1409 d->ref.ref();
1410 return true;
1411 }
1412 if (reserve == 0 && d->ref.loadRelaxed() == 1)
1413 return true;
1414
1415 QJsonPrivate::Data *x = d->clone(o, reserve);
1416 if (!x)
1417 return false;
1418 x->ref.ref();
1419 if (!d->ref.deref())
1420 delete d;
1421 d = x;
1422 o = static_cast<QJsonPrivate::Object *>(d->header->root());
1423 return true;
1424}
1425
1426/*!
1427 \internal
1428 */
1429void QJsonObject::compact()
1430{
1431 if (!d || !d->compactionCounter)
1432 return;
1433
1434 detach2();
1435 d->compact();
1436 o = static_cast<QJsonPrivate::Object *>(d->header->root());
1437}
1438
1439/*!
1440 \internal
1441 */
1442void QJsonObject::compactIfNeeded()
1443{
1444 if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u)
1445 compact();
1446}
1447
1448/*!
1449 \internal
1450 */
1451QString QJsonObject::keyAt(int i) const
1452{
1453 Q_ASSERT(o && i >= 0 && i < (int)o->length);
1454
1455 QJsonPrivate::Entry *e = o->entryAt(i);
1456 return e->key();
1457}
1458
1459/*!
1460 \internal
1461 */
1462QJsonValue QJsonObject::valueAt(int i) const
1463{
1464 if (!o || i < 0 || i >= (int)o->length)
1465 return QJsonValue(QJsonValue::Undefined);
1466
1467 QJsonPrivate::Entry *e = o->entryAt(i);
1468 return QJsonValue(d, o, e->value);
1469}
1470
1471/*!
1472 \internal
1473 */
1474void QJsonObject::setValueAt(int i, const QJsonValue &val)
1475{
1476 Q_ASSERT(o && i >= 0 && i < (int)o->length);
1477
1478 QJsonPrivate::Entry *e = o->entryAt(i);
1479 if (val.t == QJsonValue::Undefined)
1480 removeAt(i);
1481 else
1482 insertAt(i, e->key(), val, true);
1483}
1484
1485/*!
1486 \internal
1487 */
1488void QJsonObject::removeAt(int index)
1489{
1490 detach2();
1491 o->removeItems(index, 1);
1492 ++d->compactionCounter;
1493 compactIfNeeded();
1494}
1495
1496uint qHash(const QJsonObject &object, uint seed)
1497{
1498 QtPrivate::QHashCombine hash;
1499 for (auto it = object.begin(), end = object.end(); it != end; ++it) {
1500 const QString key = it.key();
1501 const QJsonValue value = it.value();
1502 seed = hash(seed, std::pair<const QString&, const QJsonValue&>(key, value));
1503 }
1504 return seed;
1505}
1506
1507#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
1508QDebug operator<<(QDebug dbg, const QJsonObject &o)
1509{
1510 QDebugStateSaver saver(dbg);
1511 if (!o.o) {
1512 dbg << "QJsonObject()";
1513 return dbg;
1514 }
1515 QByteArray json;
1516 QJsonPrivate::Writer::objectToJson(o.o, json, 0, true);
1517 dbg.nospace() << "QJsonObject("
1518 << json.constData() // print as utf-8 string without extra quotation marks
1519 << ")";
1520 return dbg;
1521}
1522#endif
1523
1524#ifndef QT_NO_DATASTREAM
1525QDataStream &operator<<(QDataStream &stream, const QJsonObject &object)
1526{
1527 QJsonDocument doc{object};
1528 stream << doc.toJson(QJsonDocument::Compact);
1529 return stream;
1530}
1531
1532QDataStream &operator>>(QDataStream &stream, QJsonObject &object)
1533{
1534 QJsonDocument doc;
1535 stream >> doc;
1536 object = doc.object();
1537 return stream;
1538}
1539#endif
1540
1541QT_END_NAMESPACE
1542