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