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

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