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

source code of qtbase/src/corelib/serialization/qjsonobject.cpp