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

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

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