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
55 QT_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 */
118 QJsonObject::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 */
QJsonObject(QCborContainerPrivate * object)137 QJsonObject::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
initialize()151 void 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(ptr, 0, sizeof(o));
158 }
159
160 /*!
161 Destroys the object.
162 */
163 QJsonObject::~QJsonObject() = default;
164
QJsonObject(std::initializer_list<QPair<QString,QJsonValue>> args)165 QJsonObject::QJsonObject(std::initializer_list<QPair<QString, QJsonValue> > args)
166 {
167 for (const auto &arg : args)
168 insert(arg.first, 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 */
QJsonObject(const QJsonObject & other)177 QJsonObject::QJsonObject(const QJsonObject &other)
178 {
179 o = other.o;
180 }
181
QJsonObject(QJsonObject && other)182 QJsonObject::QJsonObject(QJsonObject &&other) noexcept
183 : o(other.o)
184 {
185 other.o = nullptr;
186 }
187
188 /*!
189 Assigns \a other to this object.
190 */
operator =(const QJsonObject & other)191 QJsonObject &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 */
fromVariantMap(const QVariantMap & map)230 QJsonObject 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 */
toVariantMap() const242 QVariantMap QJsonObject::toVariantMap() const
243 {
244 return QCborMap::fromJsonObject(*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 */
fromVariantHash(const QVariantHash & hash)259 QJsonObject 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(it.key(), QJsonValue::fromVariant(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 */
toVariantHash() const277 QVariantHash QJsonObject::toVariantHash() const
278 {
279 return QCborMap::fromJsonObject(*this).toVariantHash();
280 }
281
282 /*!
283 Returns a list of all keys in this object.
284
285 The list is sorted lexographically.
286 */
keys() const287 QStringList QJsonObject::keys() const
288 {
289 QStringList keys;
290 if (o) {
291 keys.reserve(o->elements.length() / 2);
292 for (int i = 0, end = o->elements.length(); i < end; i += 2)
293 keys.append(o->stringAt(i));
294 }
295 return keys;
296 }
297
298 /*!
299 Returns the number of (key, value) pairs stored in the object.
300 */
size() const301 int 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 */
isEmpty() const311 bool QJsonObject::isEmpty() const
312 {
313 return !o || o->elements.isEmpty();
314 }
315
316 template<typename String>
indexOf(const QExplicitlySharedDataPointer<QCborContainerPrivate> & o,String key,bool * keyExists)317 static 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 */
value(const QString & key) const341 QJsonValue QJsonObject::value(const QString &key) const
342 {
343 return value(QStringView(key));
344 }
345 #endif
346
347 /*!
348 \overload
349 \since 5.14
350 */
value(QStringView key) const351 QJsonValue QJsonObject::value(QStringView key) const
352 {
353 return valueImpl(key);
354 }
355
356 /*!
357 \overload
358 \since 5.7
359 */
value(QLatin1String key) const360 QJsonValue QJsonObject::value(QLatin1String key) const
361 {
362 return valueImpl(key);
363 }
364
365 /*!
366 \internal
367 */
368 template <typename T>
valueImpl(T key) const369 QJsonValue 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(o->valueAt(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 */
operator [](const QString & key) const391 QJsonValue 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 */
operator [](const QString & key)425 QJsonValueRef QJsonObject::operator [](const QString &key)
426 {
427 return (*this)[QStringView(key)];
428 }
429 #endif
430
431 /*!
432 \overload
433 \since 5.14
434 */
operator [](QStringView key)435 QJsonValueRef QJsonObject::operator [](QStringView key)
436 {
437 return atImpl(key);
438 }
439
440 /*!
441 \overload
442 \since 5.7
443 */
operator [](QLatin1String key)444 QJsonValueRef QJsonObject::operator [](QLatin1String key)
445 {
446 return atImpl(key);
447 }
448
449 /*!
450 \internal
451 */
452 template <typename T>
atImpl(T key)453 QJsonValueRef 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(o->elements.length() / 2 + 1);
462 o->insertAt(index, key);
463 o->insertAt(index + 1, QCborValue::fromJsonValue(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 */
insert(const QString & key,const QJsonValue & value)483 QJsonObject::iterator QJsonObject::insert(const QString &key, const QJsonValue &value)
484 {
485 return insert(QStringView(key), value);
486 }
487 #endif
488
489 /*!
490 \overload
491 \since 5.14
492 */
insert(QStringView key,const QJsonValue & value)493 QJsonObject::iterator QJsonObject::insert(QStringView key, const QJsonValue &value)
494 {
495 return insertImpl(key, value);
496 }
497
498 /*!
499 \overload
500 \since 5.14
501 */
insert(QLatin1String key,const QJsonValue & value)502 QJsonObject::iterator QJsonObject::insert(QLatin1String key, const QJsonValue &value)
503 {
504 return insertImpl(key, value);
505 }
506
507 /*!
508 \internal
509 */
510 template <typename T>
insertImpl(T key,const QJsonValue & value)511 QJsonObject::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 */
525 template <typename T>
insertAt(int pos,T key,const QJsonValue & value,bool keyExists)526 QJsonObject::iterator QJsonObject::insertAt(int pos, T key, const QJsonValue &value, bool keyExists)
527 {
528 if (o)
529 detach2(o->elements.length() / 2 + (keyExists ? 0 : 1));
530 else
531 o = new QCborContainerPrivate;
532
533 if (keyExists) {
534 o->replaceAt(pos + 1, QCborValue::fromJsonValue(value));
535 } else {
536 o->insertAt(pos, key);
537 o->insertAt(pos + 1, QCborValue::fromJsonValue(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 */
remove(const QString & key)548 void QJsonObject::remove(const QString &key)
549 {
550 remove(QStringView(key));
551 }
552 #endif
553
554 /*!
555 \overload
556 \since 5.14
557 */
remove(QStringView key)558 void QJsonObject::remove(QStringView key)
559 {
560 removeImpl(key);
561 }
562
563 /*!
564 \overload
565 \since 5.14
566 */
remove(QLatin1String key)567 void QJsonObject::remove(QLatin1String key)
568 {
569 removeImpl(key);
570 }
571
572 /*!
573 \internal
574 */
575 template <typename T>
removeImpl(T key)576 void 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(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 */
take(const QString & key)599 QJsonValue QJsonObject::take(const QString &key)
600 {
601 return take(QStringView(key));
602 }
603 #endif
604
605 /*!
606 \overload
607 \since 5.14
608 */
take(QStringView key)609 QJsonValue QJsonObject::take(QStringView key)
610 {
611 return takeImpl(key);
612 }
613
614 /*!
615 \overload
616 \since 5.14
617 */
take(QLatin1String key)618 QJsonValue QJsonObject::take(QLatin1String key)
619 {
620 return takeImpl(key);
621 }
622
623 /*!
624 \internal
625 */
626 template <typename T>
takeImpl(T key)627 QJsonValue 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 const QJsonValue v = QJsonPrivate::Value::fromTrustedCbor(o->extractAt(index + 1));
638 removeAt(index / 2);
639 return v;
640 }
641
642 #if QT_STRINGVIEW_LEVEL < 2
643 /*!
644 Returns \c true if the object contains key \a key.
645
646 \sa insert(), remove(), take()
647 */
contains(const QString & key) const648 bool QJsonObject::contains(const QString &key) const
649 {
650 return contains(QStringView(key));
651 }
652 #endif
653
654 /*!
655 \overload
656 \since 5.14
657 */
contains(QStringView key) const658 bool QJsonObject::contains(QStringView key) const
659 {
660 return containsImpl(key);
661 }
662
663 /*!
664 \overload
665 \since 5.7
666 */
contains(QLatin1String key) const667 bool QJsonObject::contains(QLatin1String key) const
668 {
669 return containsImpl(key);
670 }
671
672 /*!
673 \internal
674 */
675 template <typename T>
containsImpl(T key) const676 bool QJsonObject::containsImpl(T key) const
677 {
678 if (!o)
679 return false;
680
681 bool keyExists;
682 indexOf(o, key, &keyExists);
683 return keyExists;
684 }
685
686 /*!
687 Returns \c true if \a other is equal to this object.
688 */
operator ==(const QJsonObject & other) const689 bool QJsonObject::operator==(const QJsonObject &other) const
690 {
691 if (o == other.o)
692 return true;
693
694 if (!o)
695 return !other.o->elements.length();
696 if (!other.o)
697 return !o->elements.length();
698 if (o->elements.length() != other.o->elements.length())
699 return false;
700
701 for (int i = 0, end = o->elements.length(); i < end; ++i) {
702 if (o->valueAt(i) != other.o->valueAt(i))
703 return false;
704 }
705
706 return true;
707 }
708
709 /*!
710 Returns \c true if \a other is not equal to this object.
711 */
operator !=(const QJsonObject & other) const712 bool QJsonObject::operator!=(const QJsonObject &other) const
713 {
714 return !(*this == other);
715 }
716
717 /*!
718 Removes the (key, value) pair pointed to by the iterator \a it
719 from the map, and returns an iterator to the next item in the
720 map.
721
722 \sa remove()
723 */
erase(QJsonObject::iterator it)724 QJsonObject::iterator QJsonObject::erase(QJsonObject::iterator it)
725 {
726 if (it.o != this || it.i < 0 || it.i >= o->elements.length())
727 return {this, o->elements.length()};
728
729 int index = it.i;
730
731 removeAt(index);
732
733 // iterator hasn't changed
734 return it;
735 }
736
737 #if QT_STRINGVIEW_LEVEL < 2
738 /*!
739 Returns an iterator pointing to the item with key \a key in the
740 map.
741
742 If the map contains no item with key \a key, the function
743 returns end().
744 */
find(const QString & key)745 QJsonObject::iterator QJsonObject::find(const QString &key)
746 {
747 return find(QStringView(key));
748 }
749 #endif
750
751 /*!
752 \overload
753 \since 5.14
754 */
find(QStringView key)755 QJsonObject::iterator QJsonObject::find(QStringView key)
756 {
757 return findImpl(key);
758 }
759
760 /*!
761 \overload
762 \since 5.7
763 */
find(QLatin1String key)764 QJsonObject::iterator QJsonObject::find(QLatin1String key)
765 {
766 return findImpl(key);
767 }
768
769 /*!
770 \internal
771 */
772 template <typename T>
findImpl(T key)773 QJsonObject::iterator QJsonObject::findImpl(T key)
774 {
775 bool keyExists = false;
776 int index = o ? indexOf(o, key, &keyExists) : 0;
777 if (!keyExists)
778 return end();
779 detach2();
780 return {this, index / 2};
781 }
782
783 #if QT_STRINGVIEW_LEVEL < 2
784 /*! \fn QJsonObject::const_iterator QJsonObject::find(const QString &key) const
785
786 \overload
787 */
788 #endif
789
790 /*! \fn QJsonObject::const_iterator QJsonObject::find(QStringView key) const
791
792 \overload
793 \since 5.14
794 */
795
796 /*! \fn QJsonObject::const_iterator QJsonObject::find(QLatin1String key) const
797
798 \overload
799 \since 5.7
800 */
801
802 #if QT_STRINGVIEW_LEVEL < 2
803 /*!
804 Returns a const iterator pointing to the item with key \a key in the
805 map.
806
807 If the map contains no item with key \a key, the function
808 returns constEnd().
809 */
constFind(const QString & key) const810 QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const
811 {
812 return constFind(QStringView(key));
813 }
814 #endif
815
816 /*!
817 \overload
818 \since 5.14
819 */
constFind(QStringView key) const820 QJsonObject::const_iterator QJsonObject::constFind(QStringView key) const
821 {
822 return constFindImpl(key);
823 }
824
825 /*!
826 \overload
827 \since 5.7
828 */
constFind(QLatin1String key) const829 QJsonObject::const_iterator QJsonObject::constFind(QLatin1String key) const
830 {
831 return constFindImpl(key);
832 }
833
834 /*!
835 \internal
836 */
837 template <typename T>
constFindImpl(T key) const838 QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
839 {
840 bool keyExists = false;
841 int index = o ? indexOf(o, key, &keyExists) : 0;
842 if (!keyExists)
843 return end();
844 return {this, index / 2};
845 }
846
847 /*! \fn int QJsonObject::count() const
848
849 \overload
850
851 Same as size().
852 */
853
854 /*! \fn int QJsonObject::length() const
855
856 \overload
857
858 Same as size().
859 */
860
861 /*! \fn QJsonObject::iterator QJsonObject::begin()
862
863 Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in
864 the object.
865
866 \sa constBegin(), end()
867 */
868
869 /*! \fn QJsonObject::const_iterator QJsonObject::begin() const
870
871 \overload
872 */
873
874 /*! \fn QJsonObject::const_iterator QJsonObject::constBegin() const
875
876 Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item
877 in the object.
878
879 \sa begin(), constEnd()
880 */
881
882 /*! \fn QJsonObject::iterator QJsonObject::end()
883
884 Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item
885 after the last item in the object.
886
887 \sa begin(), constEnd()
888 */
889
890 /*! \fn QJsonObject::const_iterator QJsonObject::end() const
891
892 \overload
893 */
894
895 /*! \fn QJsonObject::const_iterator QJsonObject::constEnd() const
896
897 Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
898 item after the last item in the object.
899
900 \sa constBegin(), end()
901 */
902
903 /*!
904 \fn bool QJsonObject::empty() const
905
906 This function is provided for STL compatibility. It is equivalent
907 to isEmpty(), returning \c true if the object is empty; otherwise
908 returning \c false.
909 */
910
911 /*! \class QJsonObject::iterator
912 \inmodule QtCore
913 \ingroup json
914 \reentrant
915 \since 5.0
916
917 \brief The QJsonObject::iterator class provides an STL-style non-const iterator for QJsonObject.
918
919 QJsonObject::iterator allows you to iterate over a QJsonObject
920 and to modify the value (but not the key) stored under
921 a particular key. If you want to iterate over a const QJsonObject, you
922 should use QJsonObject::const_iterator. It is generally good practice to
923 use QJsonObject::const_iterator on a non-const QJsonObject as well, unless you
924 need to change the QJsonObject through the iterator. Const iterators are
925 slightly faster, and improve code readability.
926
927 The default QJsonObject::iterator constructor creates an uninitialized
928 iterator. You must initialize it using a QJsonObject function like
929 QJsonObject::begin(), QJsonObject::end(), or QJsonObject::find() before you can
930 start iterating.
931
932 Multiple iterators can be used on the same object. Existing iterators will however
933 become dangling once the object gets modified.
934
935 \sa QJsonObject::const_iterator, {JSON Support in Qt}, {JSON Save Game Example}
936 */
937
938 /*! \typedef QJsonObject::iterator::difference_type
939
940 \internal
941 */
942
943 /*! \typedef QJsonObject::iterator::iterator_category
944
945 A synonym for \e {std::random_access_iterator_tag} indicating
946 this iterator is a random-access iterator.
947
948 \note In Qt versions before 5.6, this was set by mistake to
949 \e {std::bidirectional_iterator_tag}.
950 */
951
952 /*! \typedef QJsonObject::iterator::reference
953
954 \internal
955 */
956
957 /*! \typedef QJsonObject::iterator::value_type
958
959 \internal
960 */
961
962 /*! \typedef QJsonObject::iterator::pointer
963
964 \internal
965 */
966
967 /*! \fn QJsonObject::iterator::iterator()
968
969 Constructs an uninitialized iterator.
970
971 Functions like key(), value(), and operator++() must not be
972 called on an uninitialized iterator. Use operator=() to assign a
973 value to it before using it.
974
975 \sa QJsonObject::begin(), QJsonObject::end()
976 */
977
978 /*! \fn QJsonObject::iterator::iterator(QJsonObject *obj, int index)
979 \internal
980 */
981
982 /*! \fn QString QJsonObject::iterator::key() const
983
984 Returns the current item's key.
985
986 There is no direct way of changing an item's key through an
987 iterator, although it can be done by calling QJsonObject::erase()
988 followed by QJsonObject::insert().
989
990 \sa value()
991 */
992
993 /*! \fn QJsonValueRef QJsonObject::iterator::value() const
994
995 Returns a modifiable reference to the current item's value.
996
997 You can change the value of an item by using value() on
998 the left side of an assignment.
999
1000 The return value is of type QJsonValueRef, a helper class for QJsonArray
1001 and QJsonObject. When you get an object of type QJsonValueRef, you can
1002 use it as if it were a reference to a QJsonValue. If you assign to it,
1003 the assignment will apply to the element in the QJsonArray or QJsonObject
1004 from which you got the reference.
1005
1006 \sa key(), operator*()
1007 */
1008
1009 /*! \fn QJsonValueRef QJsonObject::iterator::operator*() const
1010
1011 Returns a modifiable reference to the current item's value.
1012
1013 Same as value().
1014
1015 The return value is of type QJsonValueRef, a helper class for QJsonArray
1016 and QJsonObject. When you get an object of type QJsonValueRef, you can
1017 use it as if it were a reference to a QJsonValue. If you assign to it,
1018 the assignment will apply to the element in the QJsonArray or QJsonObject
1019 from which you got the reference.
1020
1021 \sa key()
1022 */
1023
1024 /*! \fn QJsonValueRef *QJsonObject::iterator::operator->() const
1025
1026 Returns a pointer to a modifiable reference to the current item.
1027 */
1028
1029 /*! \fn const QJsonValueRef QJsonObject::iterator::operator[](int j)
1030
1031 Returns a modifiable reference to the item at offset \a j from the
1032 item pointed to by this iterator (the item at position \c{*this + j}).
1033
1034 This function is provided to make QJsonObject iterators behave like C++
1035 pointers.
1036
1037 The return value is of type QJsonValueRef, a helper class for QJsonArray
1038 and QJsonObject. When you get an object of type QJsonValueRef, you can
1039 use it as if it were a reference to a QJsonValue. If you assign to it,
1040 the assignment will apply to the element in the QJsonArray or QJsonObject
1041 from which you got the reference.
1042
1043 \sa operator+()
1044 */
1045
1046 /*!
1047 \fn bool QJsonObject::iterator::operator==(const iterator &other) const
1048 \fn bool QJsonObject::iterator::operator==(const const_iterator &other) const
1049
1050 Returns \c true if \a other points to the same item as this
1051 iterator; otherwise returns \c false.
1052
1053 \sa operator!=()
1054 */
1055
1056 /*!
1057 \fn bool QJsonObject::iterator::operator!=(const iterator &other) const
1058 \fn bool QJsonObject::iterator::operator!=(const const_iterator &other) const
1059
1060 Returns \c true if \a other points to a different item than this
1061 iterator; otherwise returns \c false.
1062
1063 \sa operator==()
1064 */
1065
1066 /*!
1067 \fn bool QJsonObject::iterator::operator<(const iterator& other) const
1068 \fn bool QJsonObject::iterator::operator<(const const_iterator& other) const
1069
1070 Returns \c true if the item pointed to by this iterator is less than
1071 the item pointed to by the \a other iterator.
1072 */
1073
1074 /*!
1075 \fn bool QJsonObject::iterator::operator<=(const iterator& other) const
1076 \fn bool QJsonObject::iterator::operator<=(const const_iterator& other) const
1077
1078 Returns \c true if the item pointed to by this iterator is less than
1079 or equal to the item pointed to by the \a other iterator.
1080 */
1081
1082 /*!
1083 \fn bool QJsonObject::iterator::operator>(const iterator& other) const
1084 \fn bool QJsonObject::iterator::operator>(const const_iterator& other) const
1085
1086 Returns \c true if the item pointed to by this iterator is greater
1087 than the item pointed to by the \a other iterator.
1088 */
1089
1090 /*!
1091 \fn bool QJsonObject::iterator::operator>=(const iterator& other) const
1092 \fn bool QJsonObject::iterator::operator>=(const const_iterator& other) const
1093
1094 Returns \c true if the item pointed to by this iterator is greater
1095 than or equal to the item pointed to by the \a other iterator.
1096 */
1097
1098 /*! \fn QJsonObject::iterator QJsonObject::iterator::operator++()
1099
1100 The prefix ++ operator, \c{++i}, advances the iterator to the
1101 next item in the object and returns an iterator to the new current
1102 item.
1103
1104 Calling this function on QJsonObject::end() leads to undefined results.
1105
1106 \sa operator--()
1107 */
1108
1109 /*! \fn QJsonObject::iterator QJsonObject::iterator::operator++(int)
1110
1111 \overload
1112
1113 The postfix ++ operator, \c{i++}, advances the iterator to the
1114 next item in the object and returns an iterator to the previously
1115 current item.
1116 */
1117
1118 /*! \fn QJsonObject::iterator QJsonObject::iterator::operator--()
1119
1120 The prefix -- operator, \c{--i}, makes the preceding item
1121 current and returns an iterator pointing to the new current item.
1122
1123 Calling this function on QJsonObject::begin() leads to undefined
1124 results.
1125
1126 \sa operator++()
1127 */
1128
1129 /*! \fn QJsonObject::iterator QJsonObject::iterator::operator--(int)
1130
1131 \overload
1132
1133 The postfix -- operator, \c{i--}, makes the preceding item
1134 current and returns an iterator pointing to the previously
1135 current item.
1136 */
1137
1138 /*! \fn QJsonObject::iterator QJsonObject::iterator::operator+(int j) const
1139
1140 Returns an iterator to the item at \a j positions forward from
1141 this iterator. If \a j is negative, the iterator goes backward.
1142
1143 \sa operator-()
1144
1145 */
1146
1147 /*! \fn QJsonObject::iterator QJsonObject::iterator::operator-(int j) const
1148
1149 Returns an iterator to the item at \a j positions backward from
1150 this iterator. If \a j is negative, the iterator goes forward.
1151
1152 \sa operator+()
1153 */
1154
1155 /*! \fn QJsonObject::iterator &QJsonObject::iterator::operator+=(int j)
1156
1157 Advances the iterator by \a j items. If \a j is negative, the
1158 iterator goes backward.
1159
1160 \sa operator-=(), operator+()
1161 */
1162
1163 /*! \fn QJsonObject::iterator &QJsonObject::iterator::operator-=(int j)
1164
1165 Makes the iterator go back by \a j items. If \a j is negative,
1166 the iterator goes forward.
1167
1168 \sa operator+=(), operator-()
1169 */
1170
1171 /*! \fn int QJsonObject::iterator::operator-(iterator other) const
1172
1173 Returns the number of items between the item pointed to by \a
1174 other and the item pointed to by this iterator.
1175 */
1176
1177 /*!
1178 \class QJsonObject::const_iterator
1179 \inmodule QtCore
1180 \ingroup json
1181 \since 5.0
1182 \brief The QJsonObject::const_iterator class provides an STL-style const iterator for QJsonObject.
1183
1184 QJsonObject::const_iterator allows you to iterate over a QJsonObject.
1185 If you want to modify the QJsonObject as you iterate
1186 over it, you must use QJsonObject::iterator instead. It is generally
1187 good practice to use QJsonObject::const_iterator on a non-const QJsonObject as
1188 well, unless you need to change the QJsonObject through the iterator.
1189 Const iterators are slightly faster and improve code
1190 readability.
1191
1192 The default QJsonObject::const_iterator constructor creates an
1193 uninitialized iterator. You must initialize it using a QJsonObject
1194 function like QJsonObject::constBegin(), QJsonObject::constEnd(), or
1195 QJsonObject::find() before you can start iterating.
1196
1197 Multiple iterators can be used on the same object. Existing iterators
1198 will however become dangling if the object gets modified.
1199
1200 \sa QJsonObject::iterator, {JSON Support in Qt}, {JSON Save Game Example}
1201 */
1202
1203 /*! \typedef QJsonObject::const_iterator::difference_type
1204
1205 \internal
1206 */
1207
1208 /*! \typedef QJsonObject::const_iterator::iterator_category
1209
1210 A synonym for \e {std::random_access_iterator_tag} indicating
1211 this iterator is a random-access iterator.
1212
1213 \note In Qt versions before 5.6, this was set by mistake to
1214 \e {std::bidirectional_iterator_tag}.
1215 */
1216
1217 /*! \typedef QJsonObject::const_iterator::reference
1218
1219 \internal
1220 */
1221
1222 /*! \typedef QJsonObject::const_iterator::value_type
1223
1224 \internal
1225 */
1226
1227 /*! \typedef QJsonObject::const_iterator::pointer
1228
1229 \internal
1230 */
1231
1232 /*! \fn QJsonObject::const_iterator::const_iterator()
1233
1234 Constructs an uninitialized iterator.
1235
1236 Functions like key(), value(), and operator++() must not be
1237 called on an uninitialized iterator. Use operator=() to assign a
1238 value to it before using it.
1239
1240 \sa QJsonObject::constBegin(), QJsonObject::constEnd()
1241 */
1242
1243 /*! \fn QJsonObject::const_iterator::const_iterator(const QJsonObject *obj, int index)
1244 \internal
1245 */
1246
1247 /*! \fn QJsonObject::const_iterator::const_iterator(const iterator &other)
1248
1249 Constructs a copy of \a other.
1250 */
1251
1252 /*! \fn QString QJsonObject::const_iterator::key() const
1253
1254 Returns the current item's key.
1255
1256 \sa value()
1257 */
1258
1259 /*! \fn QJsonValue QJsonObject::const_iterator::value() const
1260
1261 Returns the current item's value.
1262
1263 \sa key(), operator*()
1264 */
1265
1266 /*! \fn QJsonValue QJsonObject::const_iterator::operator*() const
1267
1268 Returns the current item's value.
1269
1270 Same as value().
1271
1272 \sa key()
1273 */
1274
1275 /*! \fn QJsonValue *QJsonObject::const_iterator::operator->() const
1276
1277 Returns a pointer to the current item.
1278 */
1279
1280 /*! \fn const QJsonValue QJsonObject::const_iterator::operator[](int j)
1281
1282 Returns the item at offset \a j from the item pointed to by this iterator (the item at
1283 position \c{*this + j}).
1284
1285 This function is provided to make QJsonObject iterators behave like C++
1286 pointers.
1287
1288 \sa operator+()
1289 */
1290
1291
1292 /*! \fn bool QJsonObject::const_iterator::operator==(const const_iterator &other) const
1293 \fn bool QJsonObject::const_iterator::operator==(const iterator &other) const
1294
1295 Returns \c true if \a other points to the same item as this
1296 iterator; otherwise returns \c false.
1297
1298 \sa operator!=()
1299 */
1300
1301 /*! \fn bool QJsonObject::const_iterator::operator!=(const const_iterator &other) const
1302 \fn bool QJsonObject::const_iterator::operator!=(const iterator &other) const
1303
1304 Returns \c true if \a other points to a different item than this
1305 iterator; otherwise returns \c false.
1306
1307 \sa operator==()
1308 */
1309
1310 /*!
1311 \fn bool QJsonObject::const_iterator::operator<(const const_iterator& other) const
1312
1313 Returns \c true if the item pointed to by this iterator is less than
1314 the item pointed to by the \a other iterator.
1315 */
1316
1317 /*!
1318 \fn bool QJsonObject::const_iterator::operator<=(const const_iterator& other) const
1319
1320 Returns \c true if the item pointed to by this iterator is less than
1321 or equal to the item pointed to by the \a other iterator.
1322 */
1323
1324 /*!
1325 \fn bool QJsonObject::const_iterator::operator>(const const_iterator& other) const
1326
1327 Returns \c true if the item pointed to by this iterator is greater
1328 than the item pointed to by the \a other iterator.
1329 */
1330
1331 /*!
1332 \fn bool QJsonObject::const_iterator::operator>=(const const_iterator& other) const
1333
1334 Returns \c true if the item pointed to by this iterator is greater
1335 than or equal to the item pointed to by the \a other iterator.
1336 */
1337
1338 /*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator++()
1339
1340 The prefix ++ operator, \c{++i}, advances the iterator to the
1341 next item in the object and returns an iterator to the new current
1342 item.
1343
1344 Calling this function on QJsonObject::end() leads to undefined results.
1345
1346 \sa operator--()
1347 */
1348
1349 /*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator++(int)
1350
1351 \overload
1352
1353 The postfix ++ operator, \c{i++}, advances the iterator to the
1354 next item in the object and returns an iterator to the previously
1355 current item.
1356 */
1357
1358 /*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator--()
1359
1360 The prefix -- operator, \c{--i}, makes the preceding item
1361 current and returns an iterator pointing to the new current item.
1362
1363 Calling this function on QJsonObject::begin() leads to undefined
1364 results.
1365
1366 \sa operator++()
1367 */
1368
1369 /*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator--(int)
1370
1371 \overload
1372
1373 The postfix -- operator, \c{i--}, makes the preceding item
1374 current and returns an iterator pointing to the previously
1375 current item.
1376 */
1377
1378 /*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator+(int j) const
1379
1380 Returns an iterator to the item at \a j positions forward from
1381 this iterator. If \a j is negative, the iterator goes backward.
1382
1383 This operation can be slow for large \a j values.
1384
1385 \sa operator-()
1386 */
1387
1388 /*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator-(int j) const
1389
1390 Returns an iterator to the item at \a j positions backward from
1391 this iterator. If \a j is negative, the iterator goes forward.
1392
1393 This operation can be slow for large \a j values.
1394
1395 \sa operator+()
1396 */
1397
1398 /*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator+=(int j)
1399
1400 Advances the iterator by \a j items. If \a j is negative, the
1401 iterator goes backward.
1402
1403 This operation can be slow for large \a j values.
1404
1405 \sa operator-=(), operator+()
1406 */
1407
1408 /*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator-=(int j)
1409
1410 Makes the iterator go back by \a j items. If \a j is negative,
1411 the iterator goes forward.
1412
1413 This operation can be slow for large \a j values.
1414
1415 \sa operator+=(), operator-()
1416 */
1417
1418 /*! \fn int QJsonObject::const_iterator::operator-(const_iterator other) const
1419
1420 Returns the number of items between the item pointed to by \a
1421 other and the item pointed to by this iterator.
1422 */
1423
1424
1425 /*!
1426 \internal
1427 */
detach(uint reserve)1428 void QJsonObject::detach(uint reserve)
1429 {
1430 Q_UNUSED(reserve)
1431 Q_ASSERT(!reserve);
1432 detach2(reserve);
1433 }
1434
detach2(uint reserve)1435 bool QJsonObject::detach2(uint reserve)
1436 {
1437 if (!o)
1438 return true;
1439 o = QCborContainerPrivate::detach(o.data(), reserve ? reserve * 2 : o->elements.length());
1440 return o;
1441 }
1442
1443 /*!
1444 \internal
1445 */
compact()1446 void QJsonObject::compact()
1447 {
1448 if (!o)
1449 return;
1450
1451 detach2();
1452 o->compact(o->elements.length());
1453 }
1454
1455 /*!
1456 \internal
1457 */
keyAt(int i) const1458 QString QJsonObject::keyAt(int i) const
1459 {
1460 Q_ASSERT(o && i >= 0 && i * 2 < o->elements.length());
1461 return o->stringAt(i * 2);
1462 }
1463
1464 /*!
1465 \internal
1466 */
valueAt(int i) const1467 QJsonValue QJsonObject::valueAt(int i) const
1468 {
1469 if (!o || i < 0 || 2 * i + 1 >= o->elements.length())
1470 return QJsonValue(QJsonValue::Undefined);
1471 return QJsonPrivate::Value::fromTrustedCbor(o->valueAt(2 * i + 1));
1472 }
1473
1474 /*!
1475 \internal
1476 */
setValueAt(int i,const QJsonValue & val)1477 void QJsonObject::setValueAt(int i, const QJsonValue &val)
1478 {
1479 Q_ASSERT(o && i >= 0 && 2 * i + 1 < o->elements.length());
1480 detach2();
1481 if (val.isUndefined()) {
1482 o->removeAt(2 * i + 1);
1483 o->removeAt(2 * i);
1484 } else {
1485 o->replaceAt(2 * i + 1, QCborValue::fromJsonValue(val));
1486 }
1487 }
1488
1489 /*!
1490 \internal
1491 */
removeAt(int index)1492 void QJsonObject::removeAt(int index)
1493 {
1494 detach2();
1495 o->removeAt(2 * index + 1);
1496 o->removeAt(2 * index);
1497 }
1498
qHash(const QJsonObject & object,uint seed)1499 uint qHash(const QJsonObject &object, uint seed)
1500 {
1501 QtPrivate::QHashCombine hash;
1502 for (auto it = object.begin(), end = object.end(); it != end; ++it) {
1503 const QString key = it.key();
1504 const QJsonValue value = it.value();
1505 seed = hash(seed, std::pair<const QString&, const QJsonValue&>(key, value));
1506 }
1507 return seed;
1508 }
1509
1510 #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
operator <<(QDebug dbg,const QJsonObject & o)1511 QDebug operator<<(QDebug dbg, const QJsonObject &o)
1512 {
1513 QDebugStateSaver saver(dbg);
1514 if (!o.o) {
1515 dbg << "QJsonObject()";
1516 return dbg;
1517 }
1518 QByteArray json;
1519 QJsonPrivate::Writer::objectToJson(o.o.data(), json, 0, true);
1520 dbg.nospace() << "QJsonObject("
1521 << json.constData() // print as utf-8 string without extra quotation marks
1522 << ")";
1523 return dbg;
1524 }
1525 #endif
1526
1527 #ifndef QT_NO_DATASTREAM
operator <<(QDataStream & stream,const QJsonObject & object)1528 QDataStream &operator<<(QDataStream &stream, const QJsonObject &object)
1529 {
1530 QJsonDocument doc{object};
1531 stream << doc.toJson(QJsonDocument::Compact);
1532 return stream;
1533 }
1534
operator >>(QDataStream & stream,QJsonObject & object)1535 QDataStream &operator>>(QDataStream &stream, QJsonObject &object)
1536 {
1537 QJsonDocument doc;
1538 stream >> doc;
1539 object = doc.object();
1540 return stream;
1541 }
1542 #endif
1543
1544 QT_END_NAMESPACE
1545