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