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
160 Swaps the object \a other with this. This operation is very fast and never fails.
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(o: *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(key: it.key(), value: QJsonValue::fromVariant(variant: 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(o: *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(asize: o->elements.size() / 2);
238 for (qsizetype i = 0, end = o->elements.size(); i < end; i += 2)
239 keys.append(t: o->stringAt(idx: 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(key: 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(v: o->valueAt(idx: 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(reserve: o->elements.size() / 2 + 1);
402 o->insertAt(idx: index, value: key);
403 o->insertAt(idx: index + 1, value: QCborValue::fromJsonValue(v: 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(key: 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(reserve: o->elements.size() / 2 + (keyExists ? 0 : 1));
468 else
469 o = new QCborContainerPrivate;
470
471 if (keyExists) {
472 o->replaceAt(idx: pos + 1, value: QCborValue::fromJsonValue(v: value));
473 } else {
474 o->insertAt(idx: pos, value: key);
475 o->insertAt(idx: pos + 1, value: QCborValue::fromJsonValue(v: 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(key: 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(i: 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(key: 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(v: o->extractAt(idx: index + 1));
573 removeAt(i: 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(key: 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(idx: i) != rhs.o->valueAt(idx: 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(i: 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(key: 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(key: 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/*! \class QJsonObject::iterator
836 \inmodule QtCore
837 \ingroup json
838 \reentrant
839 \since 5.0
840
841 \brief The QJsonObject::iterator class provides an STL-style non-const iterator for QJsonObject.
842
843 \compares strong
844 \compareswith strong QJsonObject::const_iterator
845 \endcompareswith
846
847 QJsonObject::iterator allows you to iterate over a QJsonObject
848 and to modify the value (but not the key) stored under
849 a particular key. If you want to iterate over a const QJsonObject, you
850 should use QJsonObject::const_iterator. It is generally good practice to
851 use QJsonObject::const_iterator on a non-const QJsonObject as well, unless you
852 need to change the QJsonObject through the iterator. Const iterators are
853 slightly faster, and improve code readability.
854
855 The default QJsonObject::iterator constructor creates an uninitialized
856 iterator. You must initialize it using a QJsonObject function like
857 QJsonObject::begin(), QJsonObject::end(), or QJsonObject::find() before you can
858 start iterating.
859
860 Multiple iterators can be used on the same object. Existing iterators will however
861 become dangling once the object gets modified.
862
863 \sa QJsonObject::const_iterator, {JSON Support in Qt}, {Saving and Loading a Game}
864*/
865
866/*! \typedef QJsonObject::iterator::difference_type
867
868 \internal
869*/
870
871/*! \typedef QJsonObject::iterator::iterator_category
872
873 A synonym for \e {std::random_access_iterator_tag} indicating
874 this iterator is a random-access iterator.
875
876 \note In Qt versions before 5.6, this was set by mistake to
877 \e {std::bidirectional_iterator_tag}.
878*/
879
880/*! \typedef QJsonObject::iterator::reference
881
882 \internal
883*/
884
885/*! \typedef QJsonObject::iterator::value_type
886
887 \internal
888*/
889
890/*! \typedef QJsonObject::iterator::pointer
891
892 \internal
893*/
894
895/*! \fn QJsonObject::iterator::iterator()
896
897 Constructs an uninitialized iterator.
898
899 Functions like key(), value(), and operator++() must not be
900 called on an uninitialized iterator. Use operator=() to assign a
901 value to it before using it.
902
903 \sa QJsonObject::begin(), QJsonObject::end()
904*/
905
906/*! \fn QJsonObject::iterator::iterator(QJsonObject *obj, qsizetype index)
907 \internal
908*/
909
910/*! \fn QString QJsonObject::iterator::key() const
911
912 Returns the current item's key.
913
914 There is no direct way of changing an item's key through an
915 iterator, although it can be done by calling QJsonObject::erase()
916 followed by QJsonObject::insert().
917
918 \sa value()
919*/
920
921/*! \fn QJsonValueRef QJsonObject::iterator::value() const
922
923 Returns a modifiable reference to the current item's value.
924
925 You can change the value of an item by using value() on
926 the left side of an assignment.
927
928 The return value is of type QJsonValueRef, a helper class for QJsonArray
929 and QJsonObject. When you get an object of type QJsonValueRef, you can
930 use it as if it were a reference to a QJsonValue. If you assign to it,
931 the assignment will apply to the element in the QJsonArray or QJsonObject
932 from which you got the reference.
933
934 \sa key(), operator*()
935*/
936
937/*! \fn QJsonValueRef QJsonObject::iterator::operator*() const
938
939 Returns a modifiable reference to the current item's value.
940
941 Same as value().
942
943 The return value is of type QJsonValueRef, a helper class for QJsonArray
944 and QJsonObject. When you get an object of type QJsonValueRef, you can
945 use it as if it were a reference to a QJsonValue. If you assign to it,
946 the assignment will apply to the element in the QJsonArray or QJsonObject
947 from which you got the reference.
948
949 \sa key()
950*/
951
952/*! \fn QJsonValueRef *QJsonObject::iterator::operator->()
953
954 Returns a pointer to a modifiable reference to the current item.
955*/
956
957/*! \fn const QJsonValueConstRef *QJsonObject::iterator::operator->() const
958
959 Returns a pointer to a constant reference to the current item.
960*/
961
962/*! \fn const QJsonValueRef QJsonObject::iterator::operator[](qsizetype j) const
963
964 Returns a modifiable reference to the item at offset \a j from the
965 item pointed to by this iterator (the item at position \c{*this + j}).
966
967 This function is provided to make QJsonObject iterators behave like C++
968 pointers.
969
970 The return value is of type QJsonValueRef, a helper class for QJsonArray
971 and QJsonObject. When you get an object of type QJsonValueRef, you can
972 use it as if it were a reference to a QJsonValue. If you assign to it,
973 the assignment will apply to the element in the QJsonArray or QJsonObject
974 from which you got the reference.
975
976 \sa operator+()
977*/
978
979/*!
980 \fn bool QJsonObject::iterator::operator==(const iterator &lhs, const iterator &rhs)
981 \fn bool QJsonObject::iterator::operator==(const iterator &lhs, const const_iterator &rhs)
982
983 Returns \c true if \a lhs points to the same item as \a rhs
984 iterator; otherwise returns \c false.
985
986 \sa operator!=()
987*/
988
989/*!
990 \fn bool QJsonObject::iterator::operator!=(const iterator &lhs, const iterator &rhs)
991 \fn bool QJsonObject::iterator::operator!=(const iterator &lhs, const const_iterator &rhs)
992
993 Returns \c true if \a lhs points to a different item than \a rhs
994 iterator; otherwise returns \c false.
995
996 \sa operator==()
997*/
998
999/*!
1000 \fn bool QJsonObject::iterator::operator<(const iterator &lhs, const iterator &rhs)
1001 \fn bool QJsonObject::iterator::operator<(const iterator &lhs, const const_iterator &rhs)
1002
1003 Returns \c true if the item pointed to by \a lhs iterator is less than
1004 the item pointed to by the \a rhs iterator.
1005*/
1006
1007/*!
1008 \fn bool QJsonObject::iterator::operator<=(const iterator &lhs, const iterator &rhs)
1009 \fn bool QJsonObject::iterator::operator<=(const iterator &lhs, const const_iterator &rhs)
1010
1011 Returns \c true if the item pointed to by \a lhs iterator is less than
1012 or equal to the item pointed to by the \a rhs iterator.
1013*/
1014
1015/*!
1016 \fn bool QJsonObject::iterator::operator>(const iterator &lhs, const iterator &rhs)
1017 \fn bool QJsonObject::iterator::operator>(const iterator &lhs, const const_iterator &rhs)
1018
1019 Returns \c true if the item pointed to by \a lhs iterator is greater
1020 than the item pointed to by the \a rhs iterator.
1021*/
1022
1023/*!
1024 \fn bool QJsonObject::iterator::operator>=(const iterator &lhs, const iterator &rhs)
1025 \fn bool QJsonObject::iterator::operator>=(const iterator &lhs, const const_iterator &rhs)
1026
1027 Returns \c true if the item pointed to by \a lhs iterator is greater
1028 than or equal to the item pointed to by the \a rhs iterator.
1029*/
1030
1031/*! \fn QJsonObject::iterator QJsonObject::iterator::operator++()
1032
1033 The prefix \c{++} operator, \c{++i}, advances the iterator to the
1034 next item in the object and returns an iterator to the new current
1035 item.
1036
1037 Calling this function on QJsonObject::end() leads to undefined results.
1038
1039 \sa operator--()
1040*/
1041
1042/*! \fn QJsonObject::iterator QJsonObject::iterator::operator++(int)
1043
1044 \overload
1045
1046 The postfix \c{++} operator, \c{i++}, advances the iterator to the
1047 next item in the object and returns an iterator to the previously
1048 current item.
1049*/
1050
1051/*! \fn QJsonObject::iterator QJsonObject::iterator::operator--()
1052
1053 The prefix \c{--} operator, \c{--i}, makes the preceding item
1054 current and returns an iterator pointing to the new current item.
1055
1056 Calling this function on QJsonObject::begin() leads to undefined
1057 results.
1058
1059 \sa operator++()
1060*/
1061
1062/*! \fn QJsonObject::iterator QJsonObject::iterator::operator--(int)
1063
1064 \overload
1065
1066 The postfix \c{--} operator, \c{i--}, makes the preceding item
1067 current and returns an iterator pointing to the previously
1068 current item.
1069*/
1070
1071/*! \fn QJsonObject::iterator QJsonObject::iterator::operator+(qsizetype j) const
1072
1073 Returns an iterator to the item at \a j positions forward from
1074 this iterator. If \a j is negative, the iterator goes backward.
1075
1076 \sa operator-()
1077
1078*/
1079
1080/*! \fn QJsonObject::iterator QJsonObject::iterator::operator-(qsizetype j) const
1081
1082 Returns an iterator to the item at \a j positions backward from
1083 this iterator. If \a j is negative, the iterator goes forward.
1084
1085 \sa operator+()
1086*/
1087
1088/*! \fn QJsonObject::iterator &QJsonObject::iterator::operator+=(qsizetype j)
1089
1090 Advances the iterator by \a j items. If \a j is negative, the
1091 iterator goes backward.
1092
1093 \sa operator-=(), operator+()
1094*/
1095
1096/*! \fn QJsonObject::iterator &QJsonObject::iterator::operator-=(qsizetype j)
1097
1098 Makes the iterator go back by \a j items. If \a j is negative,
1099 the iterator goes forward.
1100
1101 \sa operator+=(), operator-()
1102*/
1103
1104/*! \fn qsizetype QJsonObject::iterator::operator-(iterator other) const
1105
1106 Returns the number of items between the item pointed to by \a
1107 other and the item pointed to by this iterator.
1108*/
1109
1110/*!
1111 \class QJsonObject::const_iterator
1112 \inmodule QtCore
1113 \ingroup json
1114 \since 5.0
1115 \brief The QJsonObject::const_iterator class provides an STL-style const iterator for QJsonObject.
1116
1117 \compares strong
1118 \compareswith strong QJsonObject::iterator
1119 \endcompareswith
1120
1121 QJsonObject::const_iterator allows you to iterate over a QJsonObject.
1122 If you want to modify the QJsonObject as you iterate
1123 over it, you must use QJsonObject::iterator instead. It is generally
1124 good practice to use QJsonObject::const_iterator on a non-const QJsonObject as
1125 well, unless you need to change the QJsonObject through the iterator.
1126 Const iterators are slightly faster and improve code
1127 readability.
1128
1129 The default QJsonObject::const_iterator constructor creates an
1130 uninitialized iterator. You must initialize it using a QJsonObject
1131 function like QJsonObject::constBegin(), QJsonObject::constEnd(), or
1132 QJsonObject::find() before you can start iterating.
1133
1134 Multiple iterators can be used on the same object. Existing iterators
1135 will however become dangling if the object gets modified.
1136
1137 \sa QJsonObject::iterator, {JSON Support in Qt}, {Saving and Loading a Game}
1138*/
1139
1140/*! \typedef QJsonObject::const_iterator::difference_type
1141
1142 \internal
1143*/
1144
1145/*! \typedef QJsonObject::const_iterator::iterator_category
1146
1147 A synonym for \e {std::random_access_iterator_tag} indicating
1148 this iterator is a random-access iterator.
1149
1150 \note In Qt versions before 5.6, this was set by mistake to
1151 \e {std::bidirectional_iterator_tag}.
1152*/
1153
1154/*! \typedef QJsonObject::const_iterator::reference
1155
1156 \internal
1157*/
1158
1159/*! \typedef QJsonObject::const_iterator::value_type
1160
1161 \internal
1162*/
1163
1164/*! \typedef QJsonObject::const_iterator::pointer
1165
1166 \internal
1167*/
1168
1169/*! \fn QJsonObject::const_iterator::const_iterator()
1170
1171 Constructs an uninitialized iterator.
1172
1173 Functions like key(), value(), and operator++() must not be
1174 called on an uninitialized iterator. Use operator=() to assign a
1175 value to it before using it.
1176
1177 \sa QJsonObject::constBegin(), QJsonObject::constEnd()
1178*/
1179
1180/*! \fn QJsonObject::const_iterator::const_iterator(const QJsonObject *obj, qsizetype index)
1181 \internal
1182*/
1183
1184/*! \fn QJsonObject::const_iterator::const_iterator(const iterator &other)
1185
1186 Constructs a copy of \a other.
1187*/
1188
1189/*! \fn QString QJsonObject::const_iterator::key() const
1190
1191 Returns the current item's key.
1192
1193 \sa value()
1194*/
1195
1196/*! \fn QJsonValueConstRef QJsonObject::const_iterator::value() const
1197
1198 Returns the current item's value.
1199
1200 \sa key(), operator*()
1201*/
1202
1203/*! \fn const QJsonValueConstRef QJsonObject::const_iterator::operator*() const
1204
1205 Returns the current item's value.
1206
1207 Same as value().
1208
1209 \sa key()
1210*/
1211
1212/*! \fn const QJsonValueConstRef *QJsonObject::const_iterator::operator->() const
1213
1214 Returns a pointer to the current item.
1215*/
1216
1217/*! \fn const QJsonValueConstRef QJsonObject::const_iterator::operator[](qsizetype j) const
1218
1219 Returns the item at offset \a j from the item pointed to by this iterator (the item at
1220 position \c{*this + j}).
1221
1222 This function is provided to make QJsonObject iterators behave like C++
1223 pointers.
1224
1225 \sa operator+()
1226*/
1227
1228
1229/*! \fn bool QJsonObject::const_iterator::operator==(const const_iterator &lhs, const const_iterator &rhs)
1230
1231 Returns \c true if \a lhs points to the same item as \a rhs
1232 iterator; otherwise returns \c false.
1233
1234 \sa operator!=()
1235*/
1236
1237/*! \fn bool QJsonObject::const_iterator::operator!=(const const_iterator &lhs, const const_iterator &rhs)
1238
1239 Returns \c true if \a lhs points to a different item than \a rhs
1240 iterator; otherwise returns \c false.
1241
1242 \sa operator==()
1243*/
1244
1245/*!
1246 \fn bool QJsonObject::const_iterator::operator<(const const_iterator &lhs, const const_iterator &rhs)
1247
1248 Returns \c true if the item pointed to by \a lhs iterator is less than
1249 the item pointed to by the \a rhs iterator.
1250*/
1251
1252/*!
1253 \fn bool QJsonObject::const_iterator::operator<=(const const_iterator &lhs, const const_iterator &rhs)
1254
1255 Returns \c true if the item pointed to by \a lhs iterator is less than
1256 or equal to the item pointed to by the \a rhs iterator.
1257*/
1258
1259/*!
1260 \fn bool QJsonObject::const_iterator::operator>(const const_iterator &lhs, const const_iterator &rhs)
1261
1262 Returns \c true if the item pointed to by \a lhs iterator is greater
1263 than the item pointed to by the \a rhs iterator.
1264*/
1265
1266/*!
1267 \fn bool QJsonObject::const_iterator::operator>=(const const_iterator &lhs, const const_iterator &rhs)
1268
1269 Returns \c true if the item pointed to by \a lhs iterator is greater
1270 than or equal to the item pointed to by the \a rhs iterator.
1271*/
1272
1273/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator++()
1274
1275 The prefix \c{++} operator, \c{++i}, advances the iterator to the
1276 next item in the object and returns an iterator to the new current
1277 item.
1278
1279 Calling this function on QJsonObject::end() leads to undefined results.
1280
1281 \sa operator--()
1282*/
1283
1284/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator++(int)
1285
1286 \overload
1287
1288 The postfix \c{++} operator, \c{i++}, advances the iterator to the
1289 next item in the object and returns an iterator to the previously
1290 current item.
1291*/
1292
1293/*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator--()
1294
1295 The prefix \c{--} operator, \c{--i}, makes the preceding item
1296 current and returns an iterator pointing to the new current item.
1297
1298 Calling this function on QJsonObject::begin() leads to undefined
1299 results.
1300
1301 \sa operator++()
1302*/
1303
1304/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator--(int)
1305
1306 \overload
1307
1308 The postfix \c{--} operator, \c{i--}, makes the preceding item
1309 current and returns an iterator pointing to the previously
1310 current item.
1311*/
1312
1313/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator+(qsizetype j) const
1314
1315 Returns an iterator to the item at \a j positions forward from
1316 this iterator. If \a j is negative, the iterator goes backward.
1317
1318 This operation can be slow for large \a j values.
1319
1320 \sa operator-()
1321*/
1322
1323/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator-(qsizetype j) const
1324
1325 Returns an iterator to the item at \a j positions backward from
1326 this iterator. If \a j is negative, the iterator goes forward.
1327
1328 This operation can be slow for large \a j values.
1329
1330 \sa operator+()
1331*/
1332
1333/*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator+=(qsizetype j)
1334
1335 Advances the iterator by \a j items. If \a j is negative, the
1336 iterator goes backward.
1337
1338 This operation can be slow for large \a j values.
1339
1340 \sa operator-=(), operator+()
1341*/
1342
1343/*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator-=(qsizetype j)
1344
1345 Makes the iterator go back by \a j items. If \a j is negative,
1346 the iterator goes forward.
1347
1348 This operation can be slow for large \a j values.
1349
1350 \sa operator+=(), operator-()
1351*/
1352
1353/*! \fn qsizetype QJsonObject::const_iterator::operator-(const_iterator other) const
1354
1355 Returns the number of items between the item pointed to by \a
1356 other and the item pointed to by this iterator.
1357*/
1358
1359
1360/*!
1361 \internal
1362 */
1363bool QJsonObject::detach(qsizetype reserve)
1364{
1365 if (!o)
1366 return true;
1367 o = QCborContainerPrivate::detach(d: o.data(), reserved: reserve ? reserve * 2 : o->elements.size());
1368 return o;
1369}
1370
1371#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
1372/*!
1373 \internal
1374 */
1375QString QJsonObject::keyAt(qsizetype i) const
1376{
1377 Q_ASSERT(o && i >= 0 && i * 2 < o->elements.size());
1378 return o->stringAt(idx: i * 2);
1379}
1380
1381/*!
1382 \internal
1383 */
1384QJsonValue QJsonObject::valueAt(qsizetype i) const
1385{
1386 if (!o || i < 0 || 2 * i + 1 >= o->elements.size())
1387 return QJsonValue(QJsonValue::Undefined);
1388 return QJsonPrivate::Value::fromTrustedCbor(v: o->valueAt(idx: 2 * i + 1));
1389}
1390
1391/*!
1392 \internal
1393 */
1394void QJsonObject::setValueAt(qsizetype i, const QJsonValue &val)
1395{
1396 Q_ASSERT(o && i >= 0 && 2 * i + 1 < o->elements.size());
1397 detach();
1398 if (val.isUndefined()) {
1399 o->removeAt(idx: 2 * i + 1);
1400 o->removeAt(idx: 2 * i);
1401 } else {
1402 o->replaceAt(idx: 2 * i + 1, value: QCborValue::fromJsonValue(v: val));
1403 }
1404}
1405#endif // Qt 7
1406
1407/*!
1408 \internal
1409 */
1410void QJsonObject::removeAt(qsizetype index)
1411{
1412 detach();
1413 o->removeAt(idx: index + 1);
1414 o->removeAt(idx: index);
1415}
1416
1417size_t qHash(const QJsonObject &object, size_t seed)
1418{
1419 QtPrivate::QHashCombine hash;
1420 for (auto it = object.begin(), end = object.end(); it != end; ++it) {
1421 const QString key = it.key();
1422 const QJsonValue value = it.value();
1423 seed = hash(seed, std::pair<const QString&, const QJsonValue&>(key, value));
1424 }
1425 return seed;
1426}
1427
1428#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
1429QDebug operator<<(QDebug dbg, const QJsonObject &o)
1430{
1431 QDebugStateSaver saver(dbg);
1432 if (!o.o) {
1433 dbg << "QJsonObject()";
1434 return dbg;
1435 }
1436 QByteArray json;
1437 QJsonPrivate::Writer::objectToJson(o: o.o.data(), json, indent: 0, compact: true);
1438 dbg.nospace() << "QJsonObject("
1439 << json.constData() // print as utf-8 string without extra quotation marks
1440 << ")";
1441 return dbg;
1442}
1443#endif
1444
1445#ifndef QT_NO_DATASTREAM
1446QDataStream &operator<<(QDataStream &stream, const QJsonObject &object)
1447{
1448 QJsonDocument doc{object};
1449 stream << doc.toJson(format: QJsonDocument::Compact);
1450 return stream;
1451}
1452
1453QDataStream &operator>>(QDataStream &stream, QJsonObject &object)
1454{
1455 QJsonDocument doc;
1456 stream >> doc;
1457 object = doc.object();
1458 return stream;
1459}
1460#endif
1461
1462QT_END_NAMESPACE
1463

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

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