Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
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
89QJsonObject::QJsonObject() = default;
90
109 : o(object)
110{
111}
112
116QJsonObject::~QJsonObject() = default;
117
118QJsonObject::QJsonObject(std::initializer_list<std::pair<QString, QJsonValue> > args)
119{
120 for (const auto &arg : args)
121 insert(arg.first, arg.second);
122}
123
130QJsonObject::QJsonObject(const QJsonObject &other) noexcept = default;
131
138 : o(other.o)
139{
140 other.o = nullptr;
141}
142
146QJsonObject &QJsonObject::operator =(const QJsonObject &other) noexcept = default;
147
148
163#ifndef QT_NO_VARIANT
179
188{
189 return QCborMap::fromJsonObject(*this).toVariantMap();
190}
191
205{
206 // ### this is implemented the trivial way, not the most efficient way
207
209 for (QVariantHash::const_iterator it = hash.constBegin(); it != hash.constEnd(); ++it)
210 object.insert(it.key(), QJsonValue::fromVariant(it.value()));
211 return object;
212}
213
223{
224 return QCborMap::fromJsonObject(*this).toVariantHash();
225}
226#endif // !QT_NO_VARIANT
227
234{
236 if (o) {
237 keys.reserve(o->elements.size() / 2);
238 for (qsizetype i = 0, end = o->elements.size(); i < end; i += 2)
239 keys.append(o->stringAt(i));
240 }
241 return keys;
242}
243
248{
249 return o ? o->elements.size() / 2 : 0;
250}
251
258{
259 return !o || o->elements.isEmpty();
260}
261
262template<typename String>
263static qsizetype indexOf(const QExplicitlySharedDataPointer<QCborContainerPrivate> &o,
264 String key, bool *keyExists)
265{
266 const auto begin = QJsonPrivate::ConstKeyIterator(o->elements.constBegin());
267 const auto end = QJsonPrivate::ConstKeyIterator(o->elements.constEnd());
268
269 const auto it = std::lower_bound(
270 begin, end, key,
271 [&](const QJsonPrivate::ConstKeyIterator::value_type &e, const String &key) {
272 return o->stringCompareElement(e.key(), key, QtCbor::Comparison::ForOrdering) < 0;
273 });
274
275 *keyExists = (it != end) && o->stringEqualsElement((*it).key(), key);
276 return it.it - begin.it;
277}
278
287{
288 return value(QStringView(key));
289}
290
296{
297 return valueImpl(key);
298}
299
305{
306 return valueImpl(key);
307}
308
312template <typename T>
313QJsonValue QJsonObject::valueImpl(T key) const
314{
315 if (!o)
317
318 bool keyExists;
319 auto i = indexOf(o, key, &keyExists);
320 if (!keyExists)
323}
324
335{
336 return (*this)[QStringView(key)];
337}
338
367{
368 return (*this)[QStringView(key)];
369}
370
379
388
392template <typename T>
393QJsonValueRef QJsonObject::atImpl(T key)
394{
395 if (!o)
396 o = new QCborContainerPrivate;
397
398 bool keyExists = false;
399 auto index = indexOf(o, key, &keyExists);
400 if (!keyExists) {
401 detach(o->elements.size() / 2 + 1);
402 o->insertAt(index, key);
404 }
405 // detaching will happen if and when this QJsonValueRef is assigned to
406 return QJsonValueRef(this, index / 2);
407}
408
426
435
444
448template <typename T>
449QJsonObject::iterator QJsonObject::insertImpl(T key, const QJsonValue &value)
450{
451 if (value.type() == QJsonValue::Undefined) {
452 remove(key);
453 return end();
454 }
455 bool keyExists = false;
456 auto pos = o ? indexOf(o, key, &keyExists) : 0;
457 return insertAt(pos, key, value, keyExists);
458}
459
463template <typename T>
464QJsonObject::iterator QJsonObject::insertAt(qsizetype pos, T key, const QJsonValue &value, bool keyExists)
465{
466 if (o)
467 detach(o->elements.size() / 2 + (keyExists ? 0 : 1));
468 else
469 o = new QCborContainerPrivate;
470
471 if (keyExists) {
473 } else {
474 o->insertAt(pos, key);
476 }
477 return {this, pos / 2};
478}
479
486{
488}
489
495{
496 removeImpl(key);
497}
498
504{
505 removeImpl(key);
506}
507
511template <typename T>
512void QJsonObject::removeImpl(T key)
513{
514 if (!o)
515 return;
516
517 bool keyExists;
518 auto index = indexOf(o, key, &keyExists);
519 if (!keyExists)
520 return;
521
522 removeAt(index);
523}
524
538
544{
545 return takeImpl(key);
546}
547
553{
554 return takeImpl(key);
555}
556
560template <typename T>
561QJsonValue QJsonObject::takeImpl(T key)
562{
563 if (!o)
565
566 bool keyExists;
567 auto index = indexOf(o, key, &keyExists);
568 if (!keyExists)
570
571 detach();
573 removeAt(index);
574 return v;
575}
576
583{
584 return contains(QStringView(key));
585}
586
592{
593 return containsImpl(key);
594}
595
601{
602 return containsImpl(key);
603}
604
608template <typename T>
609bool QJsonObject::containsImpl(T key) const
610{
611 if (!o)
612 return false;
613
614 bool keyExists;
615 indexOf(o, key, &keyExists);
616 return keyExists;
617}
618
624bool comparesEqual(const QJsonObject &lhs, const QJsonObject &rhs) noexcept
625{
626 if (lhs.o == rhs.o)
627 return true;
628
629 if (!lhs.o)
630 return !rhs.o->elements.size();
631 if (!rhs.o)
632 return !lhs.o->elements.size();
633 if (lhs.o->elements.size() != rhs.o->elements.size())
634 return false;
635
636 for (qsizetype i = 0, end = lhs.o->elements.size(); i < end; ++i) {
637 if (lhs.o->valueAt(i) != rhs.o->valueAt(i))
638 return false;
639 }
640
641 return true;
642}
643
658{
659 removeAt(it.item.index * 2);
660
661 // index hasn't changed; the container pointer shouldn't have changed
662 // because we shouldn't have detached (detaching happens on obtaining a
663 // non-const iterator). But just in case we did, reload the pointer.
664 return { this, qsizetype(it.item.index) };
665}
666
678
687
696
700template <typename T>
701QJsonObject::iterator QJsonObject::findImpl(T key)
702{
703 bool keyExists = false;
704 auto index = o ? indexOf(o, key, &keyExists) : 0;
705 if (!keyExists)
706 return end();
707 detach();
708 return {this, index / 2};
709}
710
739
745{
746 return constFindImpl(key);
747}
748
757
761template <typename T>
762QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
763{
764 bool keyExists = false;
765 auto index = o ? indexOf(o, key, &keyExists) : 0;
766 if (!keyExists)
767 return end();
768 return {this, index / 2};
769}
770
1363bool QJsonObject::detach(qsizetype reserve)
1364{
1365 if (!o)
1366 return true;
1368 return o;
1369}
1370
1371#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
1375QString QJsonObject::keyAt(qsizetype i) const
1376{
1377 Q_ASSERT(o && i >= 0 && i * 2 < o->elements.size());
1378 return o->stringAt(i * 2);
1379}
1380
1384QJsonValue QJsonObject::valueAt(qsizetype i) const
1385{
1386 if (!o || i < 0 || 2 * i + 1 >= o->elements.size())
1389}
1390
1394void QJsonObject::setValueAt(qsizetype i, const QJsonValue &val)
1395{
1396 Q_ASSERT(o && i >= 0 && 2 * i + 1 < o->elements.size());
1397 detach();
1398 if (val.isUndefined()) {
1399 o->removeAt(2 * i + 1);
1400 o->removeAt(2 * i);
1401 } else {
1403 }
1404}
1405#endif // Qt 7
1406
1410void QJsonObject::removeAt(qsizetype index)
1411{
1412 detach();
1413 o->removeAt(index + 1);
1414 o->removeAt(index);
1415}
1416
1417size_t qHash(const QJsonObject &object, size_t seed)
1418{
1420 for (auto it = object.begin(), end = object.end(); it != end; ++it) {
1421 const QString key = it.key();
1422 const QJsonValue value = it.value();
1423 seed = hash(seed, std::pair<const QString&, const QJsonValue&>(key, value));
1424 }
1425 return seed;
1426}
1427
1428#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
1430{
1431 QDebugStateSaver saver(dbg);
1432 if (!o.o) {
1433 dbg << "QJsonObject()";
1434 return dbg;
1435 }
1436 QByteArray json;
1437 QJsonPrivate::Writer::objectToJson(o.o.data(), json, 0, true);
1438 dbg.nospace() << "QJsonObject("
1439 << json.constData() // print as utf-8 string without extra quotation marks
1440 << ")";
1441 return dbg;
1442}
1443#endif
1444
1445#ifndef QT_NO_DATASTREAM
1447{
1448 QJsonDocument doc{object};
1450 return stream;
1451}
1452
1454{
1455 QJsonDocument doc;
1456 stream >> doc;
1457 object = doc.object();
1458 return stream;
1459}
1460#endif
1461
\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:124
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
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:46
\inmodule QtCore
\inmodule QtCore
T * data() const noexcept
Returns a pointer to the shared data object.
friend class const_iterator
Definition qhash.h:1182
\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:82
\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
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.
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:25
static QJsonValue fromVariant(const QVariant &variant)
Converts variant to a QJsonValue and returns it.
qsizetype size() const noexcept
Definition qlist.h:397
bool isEmpty() const noexcept
Definition qlist.h:401
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QHash< int, QWidget * > hash
[35multi]
QMap< QString, QString > map
[6]
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.
EGLStreamKHR stream
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
size_t qHash(const QJsonObject &object, size_t seed)
bool comparesEqual(const QJsonObject &lhs, const QJsonObject &rhs) noexcept
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:165
list indexOf("B")
QSharedPointer< T > other(t)
[5]
QJSValueList args