Qt 6.x
The Qt SDK
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
qjsonobject.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <qjsonobject.h>
5#include <qjsonvalue.h>
6#include <qjsonarray.h>
7#include <qjsondocument.h>
8#include <qstringlist.h>
9#include <qdebug.h>
10#include <qvariant.h>
11#include <qcbormap.h>
12#include <qmap.h>
13#include <qhash.h>
14
15#include <private/qcborvalue_p.h>
16#include "qjsonwriter_p.h"
17#include "qjson_p.h"
18
19#include <algorithm>
20
22
85QJsonObject::QJsonObject() = default;
86
105 : o(object)
106{
107}
108
112QJsonObject::~QJsonObject() = default;
113
115{
116 for (const auto &arg : args)
117 insert(arg.first, arg.second);
118}
119
126QJsonObject::QJsonObject(const QJsonObject &other) noexcept = default;
127
134 : o(other.o)
135{
136 other.o = nullptr;
137}
138
142QJsonObject &QJsonObject::operator =(const QJsonObject &other) noexcept = default;
143
144
172{
174}
175
184{
186}
187
201{
202 // ### this is implemented the trivial way, not the most efficient way
203
205 for (QVariantHash::const_iterator it = hash.constBegin(); it != hash.constEnd(); ++it)
206 object.insert(it.key(), QJsonValue::fromVariant(it.value()));
207 return object;
208}
209
219{
221}
222
229{
231 if (o) {
232 keys.reserve(o->elements.size() / 2);
233 for (qsizetype i = 0, end = o->elements.size(); i < end; i += 2)
234 keys.append(o->stringAt(i));
235 }
236 return keys;
237}
238
243{
244 return o ? o->elements.size() / 2 : 0;
246
253{
254 return !o || o->elements.isEmpty();
255}
256
257template<typename String>
259 String key, bool *keyExists)
260{
261 const auto begin = QJsonPrivate::ConstKeyIterator(o->elements.constBegin());
262 const auto end = QJsonPrivate::ConstKeyIterator(o->elements.constEnd());
263
264 const auto it = std::lower_bound(
265 begin, end, key,
266 [&](const QJsonPrivate::ConstKeyIterator::value_type &e, const String &key) {
267 return o->stringCompareElement(e.key(), key) < 0;
268 });
269
270 *keyExists = (it != end) && o->stringEqualsElement((*it).key(), key);
271 return it.it - begin.it;
272}
273
282{
283 return value(QStringView(key));
284}
285
291{
292 return valueImpl(key);
293}
294
300{
301 return valueImpl(key);
302}
303
307template <typename T>
308QJsonValue QJsonObject::valueImpl(T key) const
309{
310 if (!o)
312
313 bool keyExists;
314 auto i = indexOf(o, key, &keyExists);
315 if (!keyExists)
318}
319
330{
331 return (*this)[QStringView(key)];
332}
333
362{
363 return (*this)[QStringView(key)];
364}
365
371{
372 return atImpl(key);
373}
374
380{
381 return atImpl(key);
382}
383
387template <typename T>
388QJsonValueRef QJsonObject::atImpl(T key)
389{
390 if (!o)
391 o = new QCborContainerPrivate;
392
393 bool keyExists = false;
394 auto index = indexOf(o, key, &keyExists);
395 if (!keyExists) {
396 detach(o->elements.size() / 2 + 1);
397 o->insertAt(index, key);
399 }
400 // detaching will happen if and when this QJsonValueRef is assigned to
401 return QJsonValueRef(this, index / 2);
402}
403
418{
419 return insert(QStringView(key), value);
420}
421
427{
428 return insertImpl(key, value);
429}
430
436{
437 return insertImpl(key, value);
438}
439
443template <typename T>
444QJsonObject::iterator QJsonObject::insertImpl(T key, const QJsonValue &value)
445{
446 if (value.type() == QJsonValue::Undefined) {
447 remove(key);
448 return end();
449 }
450 bool keyExists = false;
451 auto pos = o ? indexOf(o, key, &keyExists) : 0;
452 return insertAt(pos, key, value, keyExists);
453}
454
458template <typename T>
459QJsonObject::iterator QJsonObject::insertAt(qsizetype pos, T key, const QJsonValue &value, bool keyExists)
460{
461 if (o)
462 detach(o->elements.size() / 2 + (keyExists ? 0 : 1));
463 else
464 o = new QCborContainerPrivate;
465
466 if (keyExists) {
468 } else {
469 o->insertAt(pos, key);
471 }
472 return {this, pos / 2};
473}
474
481{
483}
484
490{
491 removeImpl(key);
492}
493
499{
500 removeImpl(key);
501}
502
506template <typename T>
507void QJsonObject::removeImpl(T key)
508{
509 if (!o)
510 return;
511
512 bool keyExists;
513 auto index = indexOf(o, key, &keyExists);
514 if (!keyExists)
515 return;
516
517 removeAt(index);
518}
519
530{
531 return take(QStringView(key));
532}
533
539{
540 return takeImpl(key);
541}
542
548{
549 return takeImpl(key);
550}
551
555template <typename T>
556QJsonValue QJsonObject::takeImpl(T key)
557{
558 if (!o)
560
561 bool keyExists;
562 auto index = indexOf(o, key, &keyExists);
563 if (!keyExists)
565
566 detach();
568 removeAt(index);
569 return v;
570}
571
578{
579 return contains(QStringView(key));
580}
581
587{
588 return containsImpl(key);
589}
590
596{
597 return containsImpl(key);
598}
599
603template <typename T>
604bool QJsonObject::containsImpl(T key) const
605{
606 if (!o)
607 return false;
608
609 bool keyExists;
610 indexOf(o, key, &keyExists);
611 return keyExists;
612}
613
618{
619 if (o == other.o)
620 return true;
621
622 if (!o)
623 return !other.o->elements.size();
624 if (!other.o)
625 return !o->elements.size();
626 if (o->elements.size() != other.o->elements.size())
627 return false;
628
629 for (qsizetype i = 0, end = o->elements.size(); i < end; ++i) {
630 if (o->valueAt(i) != other.o->valueAt(i))
631 return false;
632 }
633
634 return true;
635}
636
641{
642 return !(*this == other);
643}
644
653{
654 removeAt(it.item.index * 2);
655
656 // index hasn't changed; the container pointer shouldn't have changed
657 // because we shouldn't have detached (detaching happens on obtaining a
658 // non-const iterator). But just in case we did, reload the pointer.
659 return { this, qsizetype(it.item.index) };
660}
661
670{
671 return find(QStringView(key));
672}
673
679{
680 return findImpl(key);
681}
682
688{
689 return findImpl(key);
690}
691
695template <typename T>
696QJsonObject::iterator QJsonObject::findImpl(T key)
697{
698 bool keyExists = false;
699 auto index = o ? indexOf(o, key, &keyExists) : 0;
700 if (!keyExists)
701 return end();
702 detach();
703 return {this, index / 2};
704}
705
731{
732 return constFind(QStringView(key));
733}
734
740{
741 return constFindImpl(key);
742}
743
749{
750 return constFindImpl(key);
751}
752
756template <typename T>
757QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
758{
759 bool keyExists = false;
760 auto index = o ? indexOf(o, key, &keyExists) : 0;
761 if (!keyExists)
762 return end();
763 return {this, index / 2};
764}
765
1352bool QJsonObject::detach(qsizetype reserve)
1353{
1354 if (!o)
1355 return true;
1357 return o;
1358}
1359
1360#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
1364QString QJsonObject::keyAt(qsizetype i) const
1365{
1366 Q_ASSERT(o && i >= 0 && i * 2 < o->elements.size());
1367 return o->stringAt(i * 2);
1368}
1369
1373QJsonValue QJsonObject::valueAt(qsizetype i) const
1374{
1375 if (!o || i < 0 || 2 * i + 1 >= o->elements.size())
1378}
1379
1383void QJsonObject::setValueAt(qsizetype i, const QJsonValue &val)
1384{
1385 Q_ASSERT(o && i >= 0 && 2 * i + 1 < o->elements.size());
1386 detach();
1387 if (val.isUndefined()) {
1388 o->removeAt(2 * i + 1);
1389 o->removeAt(2 * i);
1390 } else {
1392 }
1393}
1394#endif // Qt 7
1395
1399void QJsonObject::removeAt(qsizetype index)
1400{
1401 detach();
1402 o->removeAt(index + 1);
1403 o->removeAt(index);
1404}
1405
1406size_t qHash(const QJsonObject &object, size_t seed)
1407{
1409 for (auto it = object.begin(), end = object.end(); it != end; ++it) {
1410 const QString key = it.key();
1411 const QJsonValue value = it.value();
1412 seed = hash(seed, std::pair<const QString&, const QJsonValue&>(key, value));
1413 }
1414 return seed;
1415}
1416
1417#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
1419{
1420 QDebugStateSaver saver(dbg);
1421 if (!o.o) {
1422 dbg << "QJsonObject()";
1423 return dbg;
1424 }
1425 QByteArray json;
1426 QJsonPrivate::Writer::objectToJson(o.o.data(), json, 0, true);
1427 dbg.nospace() << "QJsonObject("
1428 << json.constData() // print as utf-8 string without extra quotation marks
1429 << ")";
1430 return dbg;
1431}
1432#endif
1433
1434#ifndef QT_NO_DATASTREAM
1436{
1437 QJsonDocument doc{object};
1439 return stream;
1440}
1441
1443{
1444 QJsonDocument doc;
1445 stream >> doc;
1446 object = doc.object();
1447 return stream;
1448}
1449#endif
1450
\inmodule QtCore
Definition qbytearray.h:57
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:122
QString stringAt(qsizetype idx) const
void insertAt(qsizetype idx, const QCborValue &value, ContainerDisposition disp=CopyContainer)
static QCborContainerPrivate * detach(QCborContainerPrivate *d, qsizetype reserved)
void removeAt(qsizetype idx)
void replaceAt(qsizetype idx, const QCborValue &value, ContainerDisposition disp=CopyContainer)
QList< QtCbor::Element > elements
QCborValue extractAt(qsizetype idx)
QCborValue valueAt(qsizetype idx) const
QVariantMap toVariantMap() const
Converts the CBOR values to QVariant using QCborValue::toVariant() and "stringifies" all the CBOR key...
QVariantHash toVariantHash() const
Converts the CBOR values to QVariant using QCborValue::toVariant() and "stringifies" all the CBOR key...
static QCborMap fromJsonObject(const QJsonObject &o)
Converts all JSON items found in the obj object to CBOR using QCborValue::fromJson(),...
static QCborValue fromJsonValue(const QJsonValue &v)
Converts the JSON value contained in v into its corresponding CBOR value and returns it.
\inmodule QtCore\reentrant
Definition qdatastream.h:30
\inmodule QtCore
\inmodule QtCore
T * data() const noexcept
Returns a pointer to the shared data object.
friend class const_iterator
Definition qhash.h:1172
\inmodule QtCore\reentrant
QByteArray toJson(JsonFormat format=Indented) const
QJsonObject object() const
Returns the QJsonObject contained in the document.
\inmodule QtCore\reentrant
Definition qjsonobject.h:81
\inmodule QtCore\reentrant
Definition qjsonobject.h:20
QVariantMap toVariantMap() const
Converts this object to a QVariantMap.
QJsonValue operator[](const QString &key) const
Returns a QJsonValue representing the value for the key key.
QJsonValue take(const QString &key)
Removes key from the object.
~QJsonObject()
Destroys the object.
iterator erase(iterator it)
Removes the (key, value) pair pointed to by the iterator it from the map, and returns an iterator to ...
iterator end()
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last ...
iterator find(const QString &key)
Returns an iterator pointing to the item with key key in the map.
qsizetype size() const
Returns the number of (key, value) pairs stored in the object.
void remove(const QString &key)
Removes key from the object.
QStringList keys() const
Returns a list of all keys in this object.
friend class QJsonValueRef
bool operator==(const QJsonObject &other) const
Returns true if other is equal to this object.
const_iterator constFind(const QString &key) const
Returns a const iterator pointing to the item with key key in the map.
iterator insert(const QString &key, const QJsonValue &value)
Inserts a new item with the key key and a value of value.
static QJsonObject fromVariantMap(const QVariantMap &map)
Converts the variant map map to a QJsonObject.
QJsonObject()
Constructs an empty JSON object.
friend class QJsonValue
QJsonValue value(const QString &key) const
Returns a QJsonValue representing the value for the key key.
QJsonObject & operator=(const QJsonObject &other) noexcept
Assigns other to this object.
bool contains(const QString &key) const
Returns true if the object contains key key.
QVariantHash toVariantHash() const
Converts this object to a QVariantHash.
bool isEmpty() const
Returns true if the object is empty.
bool operator!=(const QJsonObject &other) const
Returns true if other is not equal to this object.
static QJsonObject fromVariantHash(const QVariantHash &map)
Converts the variant hash hash to a QJsonObject.
static QJsonValue fromTrustedCbor(const QCborValue &v)
Definition qjson_p.h:200
static QJsonObject toJsonObject(const QVariantMap &map)
static void objectToJson(const QCborContainerPrivate *o, QByteArray &json, int indent, bool compact=false)
\inmodule QtCore \reentrant
\inmodule QtCore\reentrant
Definition qjsonvalue.h:24
static QJsonValue fromVariant(const QVariant &variant)
Converts variant to a QJsonValue and returns it.
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:76
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
QHash< int, QWidget * > hash
[35multi]
QMap< QString, QString > map
[6]
double e
QSet< QString >::iterator it
set reserve(20000)
ObjectIterator< const QtCbor::Element, QList< QtCbor::Element >::const_iterator > ConstKeyIterator
Definition qjson_p.h:154
Combined button and popup list for selecting options.
std::pair< T1, T2 > QPair
EGLStreamKHR stream
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
size_t qHash(const QJsonObject &object, size_t seed)
QDataStream & operator>>(QDataStream &stream, QJsonObject &object)
QDebug operator<<(QDebug dbg, const QJsonObject &o)
static qsizetype indexOf(const QExplicitlySharedDataPointer< QCborContainerPrivate > &o, String key, bool *keyExists)
GLsizei const GLfloat * v
[13]
GLuint64 key
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLuint GLuint end
GLuint object
[3]
GLuint GLfloat * val
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
Definition qrandom.cpp:196
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
SSL_CTX int(*) void arg)
static const QTextHtmlElement elements[Html_NumElements]
ptrdiff_t qsizetype
Definition qtypes.h:70
list indexOf("B")
QSharedPointer< T > other(t)
[5]
QJSValueList args