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