Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qjsonvalue.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// Copyright (C) 2022 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4// Qt-Security score:critical reason:data-parser
5
6#include <qjsonobject.h>
7#include <qjsonvalue.h>
8#include <qjsonarray.h>
9#include <qjsondocument.h>
10#include <qurl.h>
11#include <quuid.h>
12#include <qvariant.h>
13#include <qstringlist.h>
14#include <qmap.h>
15#include <qhash.h>
16#include <qdebug.h>
17#include "qdatastream.h"
18#include "qjsonparser_p.h"
19#include "qjsonwriter_p.h"
20
21#include <private/qnumeric_p.h>
22#include <private/qcborvalue_p.h>
23
24#include <qcborarray.h>
25#include <qcbormap.h>
26
27#include "qjson_p.h"
28
30
31static QJsonValue::Type convertFromCborType(QCborValue::Type type) noexcept
32{
33 switch (type) {
34 case QCborValue::Null:
35 return QJsonValue::Null;
36 case QCborValue::True:
37 case QCborValue::False:
38 return QJsonValue::Bool;
39 case QCborValue::Double:
40 case QCborValue::Integer:
41 return QJsonValue::Double;
42 case QCborValue::String:
43 return QJsonValue::String;
44 case QCborValue::Array:
45 return QJsonValue::Array;
46 case QCborValue::Map:
47 return QJsonValue::Object;
48 case QCborValue::Undefined:
49 default:
50 return QJsonValue::Undefined;
51 }
52}
53
54/*!
55 \class QJsonValue
56 \inmodule QtCore
57 \ingroup json
58 \ingroup shared
59 \ingroup qtserialization
60 \reentrant
61 \since 5.0
62
63 \brief The QJsonValue class encapsulates a value in JSON.
64
65 \compares equality
66 \compareswith equality QJsonValueConstRef QJsonValueRef
67 \endcompareswith
68
69 A value in JSON can be one of 6 basic types:
70
71 JSON is a format to store structured data. It has 6 basic data types:
72
73 \list
74 \li bool QJsonValue::Bool
75 \li double QJsonValue::Double
76 \li string QJsonValue::String
77 \li array QJsonValue::Array
78 \li object QJsonValue::Object
79 \li null QJsonValue::Null
80 \endlist
81
82 A value can represent any of the above data types. In addition, QJsonValue has one special
83 flag to represent undefined values. This can be queried with isUndefined().
84
85 The type of the value can be queried with type() or accessors like isBool(), isString(), and so on.
86 Likewise, the value can be converted to the type stored in it using the toBool(), toString() and so on.
87
88 Values are strictly typed internally and contrary to QVariant will not attempt to do any implicit type
89 conversions. This implies that converting to a type that is not stored in the value will return a default
90 constructed return value.
91
92 \section1 QJsonValueRef
93
94 QJsonValueRef is a helper class for QJsonArray and QJsonObject.
95 When you get an object of type QJsonValueRef, you can
96 use it as if it were a reference to a QJsonValue. If you assign to it,
97 the assignment will apply to the element in the QJsonArray or QJsonObject
98 from which you got the reference.
99
100 The following methods return QJsonValueRef:
101 \list
102 \li \l {QJsonArray}::operator[](qsizetype i)
103 \li \l {QJsonObject}::operator[](const QString & key) const
104 \endlist
105
106 \sa {JSON Support in Qt}, {Saving and Loading a Game}
107*/
108
109/*!
110 Creates a QJsonValue of type \a type.
111
112 The default is to create a Null value.
113 */
114QJsonValue::QJsonValue(Type type)
115{
116 switch (type) {
117 case Null:
118 value = QCborValue::Null;
119 break;
120 case Bool:
121 value = QCborValue::False;
122 break;
123 case Double:
124 value = QCborValue::Double;
125 break;
126 case String:
127 value = QCborValue::String;
128 break;
129 case Array:
130 value = QCborValue::Array;
131 break;
132 case Object:
133 value = QCborValue::Map;
134 break;
135 case Undefined:
136 break;
137 }
138}
139
140/*!
141 Creates a value of type Bool, with value \a b.
142 */
143QJsonValue::QJsonValue(bool b)
144 : value(b)
145{
146}
147
148static inline QCborValue doubleValueHelper(double v)
149{
150 qint64 n = 0;
151 // Convert to integer if the number is an integer and changing wouldn't
152 // introduce additional digit precision not present in the double.
153 if (convertDoubleTo<qint64>(v, &n, false /* allow_precision_upgrade */))
154 return n;
155 else
156 return v;
157}
158
159/*!
160 Creates a value of type Double, with value \a v.
161 */
162QJsonValue::QJsonValue(double v)
163 : value(doubleValueHelper(v))
164{
165}
166
167/*!
168 \overload
169 Creates a value of type Double, with value \a v.
170 */
171QJsonValue::QJsonValue(int v)
172 : value(v)
173{
174}
175
176/*!
177 \overload
178 Creates a value of type Double, with value \a v.
179
180 This is stored internally as a 64-bit integer, so retains its full
181 precision, as long as it is retrieved with \l toInteger(). However,
182 retrieving its value with \l toDouble() will lose precision unless the value
183 lies between ±2^53.
184
185 \sa toInteger(), toDouble()
186*/
187QJsonValue::QJsonValue(qint64 v)
188 : value(v)
189{
190}
191
192/*!
193 Creates a value of type String, with value \a s.
194 */
195QJsonValue::QJsonValue(const QString &s)
196 : value(s)
197{
198}
199
200/*!
201 \fn QJsonValue::QJsonValue(const char *s)
202
203 Creates a value of type String with value \a s, assuming
204 UTF-8 encoding of the input.
205
206 You can disable this constructor by defining \c
207 QT_NO_CAST_FROM_ASCII when you compile your applications.
208
209 \since 5.3
210 */
211
212/*!
213 Creates a value of type String, with the Latin-1 string viewed by \a s.
214 */
215QJsonValue::QJsonValue(QLatin1StringView s)
216 : value(s)
217{
218}
219
220/*!
221 Creates a value of type Array, with value \a a.
222 */
223QJsonValue::QJsonValue(const QJsonArray &a)
224 : value(QCborArray::fromJsonArray(a))
225{
226}
227
228/*!
229 \overload
230 \since 6.3
231 */
232QJsonValue::QJsonValue(QJsonArray &&a) noexcept
233 : value(QCborArray::fromJsonArray(std::move(a)))
234{
235}
236
237/*!
238 Creates a value of type Object, with value \a o.
239 */
240QJsonValue::QJsonValue(const QJsonObject &o)
241 : value(QCborMap::fromJsonObject(o))
242{
243}
244
245/*!
246 \overload
247 \since 6.3
248 */
249QJsonValue::QJsonValue(QJsonObject &&o) noexcept
250 : value(QCborMap::fromJsonObject(std::move(o)))
251{
252}
253
254
255/*!
256 Destroys the value.
257 */
258QJsonValue::~QJsonValue() = default;
259
260/*!
261 Creates a copy of \a other.
262 */
263QJsonValue::QJsonValue(const QJsonValue &other) noexcept = default;
264
265/*!
266 Assigns the value stored in \a other to this object.
267 */
268QJsonValue &QJsonValue::operator =(const QJsonValue &other) noexcept
269{
270 QJsonValue copy(other);
271 swap(copy);
272 return *this;
273}
274
275QJsonValue::QJsonValue(QJsonValue &&other) noexcept
276 : value(std::move(other.value))
277{
278 other.value = QCborValue(nullptr);
279}
280
281void QJsonValue::swap(QJsonValue &other) noexcept
282{
283 value.swap(other.value);
284}
285
286/*!
287 \fn QJsonValue::QJsonValue(QJsonValue &&other)
288 \since 5.10
289
290 Move-constructs a QJsonValue from \a other.
291*/
292
293/*!
294 \fn QJsonValue &QJsonValue::operator =(QJsonValue &&other)
295 \since 5.10
296
297 Move-assigns \a other to this value.
298*/
299
300/*!
301 \fn void QJsonValue::swap(QJsonValue &other)
302 \since 5.10
303 \memberswap{value}
304*/
305
306/*!
307 \fn bool QJsonValue::isNull() const
308
309 Returns \c true if the value is null.
310*/
311
312/*!
313 \fn bool QJsonValue::isBool() const
314
315 Returns \c true if the value contains a boolean.
316
317 \sa toBool()
318 */
319
320/*!
321 \fn bool QJsonValue::isDouble() const
322
323 Returns \c true if the value contains a double.
324
325 \sa toDouble()
326 */
327
328/*!
329 \fn bool QJsonValue::isString() const
330
331 Returns \c true if the value contains a string.
332
333 \sa toString()
334 */
335
336/*!
337 \fn bool QJsonValue::isArray() const
338
339 Returns \c true if the value contains an array.
340
341 \sa toArray()
342 */
343
344/*!
345 \fn bool QJsonValue::isObject() const
346
347 Returns \c true if the value contains an object.
348
349 \sa toObject()
350 */
351
352/*!
353 \fn bool QJsonValue::isUndefined() const
354
355 Returns \c true if the value is undefined. This can happen in certain
356 error cases as e.g. accessing a non existing key in a QJsonObject.
357 */
358
359#ifndef QT_NO_VARIANT
360/*!
361 Converts \a variant to a QJsonValue and returns it.
362
363 The conversion will convert QVariant types as follows:
364
365 \table
366 \header
367 \li Source type
368 \li Destination type
369 \row
370 \li
371 \list
372 \li QMetaType::Nullptr
373 \endlist
374 \li QJsonValue::Null
375 \row
376 \li
377 \list
378 \li QMetaType::Bool
379 \endlist
380 \li QJsonValue::Bool
381 \row
382 \li
383 \list
384 \li QMetaType::Int
385 \li QMetaType::UInt
386 \li QMetaType::LongLong
387 \li QMetaType::ULongLong
388 \li QMetaType::Float
389 \li QMetaType::Double
390 \endlist
391 \li QJsonValue::Double
392 \row
393 \li
394 \list
395 \li QMetaType::QString
396 \endlist
397 \li QJsonValue::String
398 \row
399 \li
400 \list
401 \li QMetaType::QStringList
402 \li QMetaType::QVariantList
403 \endlist
404 \li QJsonValue::Array
405 \row
406 \li
407 \list
408 \li QMetaType::QVariantMap
409 \li QMetaType::QVariantHash
410 \endlist
411 \li QJsonValue::Object
412
413 \row
414 \li
415 \list
416 \li QMetaType::QUrl
417 \endlist
418 \li QJsonValue::String. The conversion will use QUrl::toString() with flag
419 QUrl::FullyEncoded, so as to ensure maximum compatibility in parsing the URL
420 \row
421 \li
422 \list
423 \li QMetaType::QUuid
424 \endlist
425 \li QJsonValue::String. Since Qt 5.11, the resulting string will not include braces
426 \row
427 \li
428 \list
429 \li QMetaType::QCborValue
430 \endlist
431 \li Whichever type QCborValue::toJsonValue() returns.
432 \row
433 \li
434 \list
435 \li QMetaType::QCborArray
436 \endlist
437 \li QJsonValue::Array. See QCborValue::toJsonValue() for conversion restrictions.
438 \row
439 \li
440 \list
441 \li QMetaType::QCborMap
442 \endlist
443 \li QJsonValue::Map. See QCborValue::toJsonValue() for conversion restrictions and the
444 "stringification" of map keys.
445 \endtable
446
447 \section2 Loss of information and other types
448
449 QVariant can carry more information than is representable in JSON. If the
450 QVariant is not one of the types above, the conversion is not guaranteed
451 and is subject to change in future versions of Qt, as the UUID one did.
452 Code should strive not to use any other types than those listed above.
453
454 If QVariant::isNull() returns true, a null QJsonValue is returned or
455 inserted into the list or object, regardless of the type carried by
456 QVariant. Note the behavior change in Qt 6.0 affecting QVariant::isNull()
457 also affects this function.
458
459 A floating point value that is either an infinity or NaN will be converted
460 to a null JSON value. Since Qt 6.0, QJsonValue can store the full precision
461 of any 64-bit signed integer without loss, but in previous versions values
462 outside the range of ±2^53 may lose precision. Unsigned 64-bit values
463 greater than or equal to 2^63 will either lose precision or alias to
464 negative values, so QMetaType::ULongLong should be avoided.
465
466 For other types not listed above, a conversion to string will be attempted,
467 usually but not always by calling QVariant::toString(). If the conversion
468 fails the value is replaced by a null JSON value. Note that
469 QVariant::toString() is also lossy for the majority of types. For example,
470 if the passed QVariant is representing raw byte array data, it is recommended
471 to pre-encode it to \l {RFC 4686}{Base64} (or
472 another lossless encoding), otherwise a lossy conversion using QString::fromUtf8()
473 will be used.
474
475 Please note that the conversions via QVariant::toString() are subject to
476 change at any time. Both QVariant and QJsonValue may be extended in the
477 future to support more types, which will result in a change in how this
478 function performs conversions.
479
480 \sa toVariant(), QCborValue::fromVariant()
481 */
482QJsonValue QJsonValue::fromVariant(const QVariant &variant)
483{
484 switch (variant.metaType().id()) {
485 case QMetaType::Nullptr:
486 return QJsonValue(Null);
487 case QMetaType::Bool:
488 return QJsonValue(variant.toBool());
489 case QMetaType::Short:
490 case QMetaType::UShort:
491 case QMetaType::Int:
492 case QMetaType::UInt:
493 case QMetaType::Long:
494 case QMetaType::LongLong:
495 return QJsonValue(variant.toLongLong());
496 case QMetaType::ULong:
497 case QMetaType::ULongLong:
498 if (variant.toULongLong() <= static_cast<uint64_t>(std::numeric_limits<qint64>::max()))
499 return QJsonValue(variant.toLongLong());
500 Q_FALLTHROUGH();
501 case QMetaType::Float16:
502 case QMetaType::Float:
503 case QMetaType::Double: {
504 double v = variant.toDouble();
505 return qt_is_finite(v) ? QJsonValue(v) : QJsonValue();
506 }
507 case QMetaType::QString:
508 return QJsonValue(variant.toString());
509 case QMetaType::QStringList:
510 return QJsonValue(QJsonArray::fromStringList(variant.toStringList()));
511 case QMetaType::QVariantList:
512 return QJsonValue(QJsonArray::fromVariantList(variant.toList()));
513 case QMetaType::QVariantMap:
514 return QJsonValue(QJsonObject::fromVariantMap(variant.toMap()));
515 case QMetaType::QVariantHash:
516 return QJsonValue(QJsonObject::fromVariantHash(variant.toHash()));
517#ifndef QT_BOOTSTRAPPED
518 case QMetaType::QUrl:
519 return QJsonValue(variant.toUrl().toString(QUrl::FullyEncoded));
520 case QMetaType::QUuid:
521 return variant.toUuid().toString(QUuid::WithoutBraces);
522 case QMetaType::QJsonValue:
523 return variant.toJsonValue();
524 case QMetaType::QJsonObject:
525 return variant.toJsonObject();
526 case QMetaType::QJsonArray:
527 return variant.toJsonArray();
528 case QMetaType::QJsonDocument: {
529 QJsonDocument doc = variant.toJsonDocument();
530 return doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object());
531 }
532 case QMetaType::QCborValue:
533 return qvariant_cast<QCborValue>(variant).toJsonValue();
534 case QMetaType::QCborArray:
535 return qvariant_cast<QCborArray>(variant).toJsonArray();
536 case QMetaType::QCborMap:
537 return qvariant_cast<QCborMap>(variant).toJsonObject();
538#endif
539 default:
540 break;
541 }
542 QString string = variant.toString();
543 if (string.isEmpty())
544 return QJsonValue();
545 return QJsonValue(string);
546}
547
548/*!
549 Converts the value to a \l {QVariant::}{QVariant()}.
550
551 The QJsonValue types will be converted as follows:
552
553 \value Null QMetaType::Nullptr
554 \value Bool QMetaType::Bool
555 \value Double QMetaType::Double or QMetaType::LongLong
556 \value String QString
557 \value Array QVariantList
558 \value Object QVariantMap
559 \value Undefined \l {QVariant::}{QVariant()}
560
561 \sa fromVariant()
562 */
563QVariant QJsonValue::toVariant() const
564{
565 switch (value.type()) {
566 case QCborValue::True:
567 return true;
568 case QCborValue::False:
569 return false;
570 case QCborValue::Integer:
571 return toInteger();
572 case QCborValue::Double:
573 return toDouble();
574 case QCborValue::String:
575 return toString();
576 case QCborValue::Array:
577 return toArray().toVariantList();
578 case QCborValue::Map:
579 return toObject().toVariantMap();
580 case QCborValue::Null:
581 return QVariant::fromValue(nullptr);
582 case QCborValue::Undefined:
583 default:
584 break;
585 }
586 return QVariant();
587}
588
589/*!
590 \enum QJsonValue::Type
591
592 This enum describes the type of the JSON value.
593
594 \value Null A Null value
595 \value Bool A boolean value. Use toBool() to convert to a bool.
596 \value Double A number value. Use toDouble() to convert to a double,
597 or toInteger() to convert to a qint64.
598 \value String A string. Use toString() to convert to a QString.
599 \value Array An array. Use toArray() to convert to a QJsonArray.
600 \value Object An object. Use toObject() to convert to a QJsonObject.
601 \value Undefined The value is undefined. This is usually returned as an
602 error condition, when trying to read an out of bounds value
603 in an array or a non existent key in an object.
604*/
605#endif // !QT_NO_VARIANT
606
607/*!
608 \since 6.9
609 Parses \a json as a UTF-8 encoded JSON value, and creates a QJsonValue
610 from it.
611
612 Returns a valid QJsonValue if the parsing succeeds. If it fails, the
613 returned value will be \l {QJsonValue::isUndefined} {undefined}, and
614 the optional \a error variable will contain further details about the
615 error.
616
617 \sa QJsonParseError, isUndefined(), toJson()
618 */
619QJsonValue QJsonValue::fromJson(QByteArrayView json, QJsonParseError *error)
620{
621 QJsonPrivate::Parser parser(json);
622 QJsonValue result;
623 result.value = parser.parse(error);
624 return result;
625}
626
627/*!
628\if defined(qt7)
629 \enum QJsonValue::JsonFormat
630 \since 6.9
631
632 This value defines the format of the JSON byte array produced
633 when converting to a QJsonValue using toJson().
634
635 \value Indented Defines human readable output as follows:
636 \snippet code/src_corelib_serialization_qjsondocument.cpp 0
637
638 \value Compact Defines a compact output as follows:
639 \snippet code/src_corelib_serialization_qjsondocument.cpp 1
640\else
641 \typealias QJsonValue::JsonFormat
642 \since 6.9
643
644 Same as \l QJsonDocument::JsonFormat.
645\endif
646*/
647
648/*!
649 \since 6.9
650 Converts the QJsonValue to a UTF-8 encoded JSON value in the provided \a format.
651
652 \sa fromJson(), JsonFormat
653 */
654QByteArray QJsonValue::toJson(JsonFormat format) const
655{
656 QByteArray json;
657
658 QJsonPrivate::Writer::valueToJson(value, json, 0, (format == JsonFormat::Compact));
659
660 return json;
661}
662
663/*!
664 Returns the type of the value.
665
666 \sa QJsonValue::Type
667 */
668QJsonValue::Type QJsonValue::type() const
669{
670 return convertFromCborType(value.type());
671}
672
673/*!
674 Converts the value to a bool and returns it.
675
676 If type() is not bool, the \a defaultValue will be returned.
677 */
678bool QJsonValue::toBool(bool defaultValue) const
679{
680 switch (value.type()) {
681 case QCborValue::True:
682 return true;
683 case QCborValue::False:
684 return false;
685 default:
686 return defaultValue;
687 }
688}
689
690/*!
691 \since 5.2
692 Converts the value to an int and returns it.
693
694 If type() is not Double or the value is not a whole number,
695 the \a defaultValue will be returned.
696 */
697int QJsonValue::toInt(int defaultValue) const
698{
699 switch (value.type()) {
700 case QCborValue::Double: {
701 int dblInt;
702 if (convertDoubleTo<int>(toDouble(), &dblInt))
703 return dblInt;
704 break;
705 }
706 case QCborValue::Integer: {
707 const auto n = value.toInteger();
708 if (qint64(int(n)) == n)
709 return int(n);
710 break;
711 }
712 default:
713 break;
714 }
715 return defaultValue;
716}
717
718/*!
719 \since 6.0
720 Converts the value to an integer and returns it.
721
722 If type() is not Double or the value is not a whole number
723 representable as qint64, the \a defaultValue will be returned.
724 */
725qint64 QJsonValue::toInteger(qint64 defaultValue) const
726{
727 switch (value.type()) {
728 case QCborValue::Integer:
729 return value.toInteger();
730 case QCborValue::Double: {
731 qint64 dblInt;
732 if (convertDoubleTo<qint64>(toDouble(), &dblInt))
733 return dblInt;
734 break;
735 }
736 default:
737 break;
738 }
739 return defaultValue;
740}
741
742/*!
743 Converts the value to a double and returns it.
744
745 If type() is not Double, the \a defaultValue will be returned.
746 */
747double QJsonValue::toDouble(double defaultValue) const
748{
749 return value.toDouble(defaultValue);
750}
751
752/*!
753 Converts the value to a QString and returns it.
754
755 If type() is not String, the \a defaultValue will be returned.
756
757 \sa toStringView()
758 */
759QString QJsonValue::toString(const QString &defaultValue) const
760{
761 return value.toString(defaultValue);
762}
763
764/*!
765 \since 6.10
766
767 Returns the string value stored in this QJsonValue, if it is of the
768 \l{String}{string} type. Otherwise, it returns \a defaultValue. Since
769 QJsonValue stores strings in either US-ASCII, UTF-8 or UTF-16, the returned
770 QAnyStringView may be in any of these encodings.
771
772 This function does not allocate memory. The return value is valid until the
773 next call to a non-const member function on this object. If this object goes
774 out of scope, the return value is valid until the next call to a non-const
775 member function on the parent JSON object or array.
776
777 \sa toString()
778*/
779QAnyStringView QJsonValue::toStringView(QAnyStringView defaultValue) const
780{
781 return value.toStringView(defaultValue);
782}
783
784/*!
785 Converts the value to a QString and returns it.
786
787 If type() is not String, a null QString will be returned.
788
789 \sa QString::isNull()
790 */
791QString QJsonValue::toString() const
792{
793 return value.toString();
794}
795
796/*!
797 Converts the value to an array and returns it.
798
799 If type() is not Array, the \a defaultValue will be returned.
800 */
801QJsonArray QJsonValue::toArray(const QJsonArray &defaultValue) const
802{
803 if (!isArray())
804 return defaultValue;
805 QCborContainerPrivate *dd = nullptr;
806 const auto n = QJsonPrivate::Value::valueHelper(value);
807 const auto container = QJsonPrivate::Value::container(value);
808 Q_ASSERT(n == -1 || container == nullptr);
809 if (n < 0)
810 dd = container;
811 return QJsonArray(dd);
812}
813
814/*!
815 \overload
816
817 Converts the value to an array and returns it.
818
819 If type() is not Array, a \l{QJsonArray::}{QJsonArray()} will be returned.
820 */
821QJsonArray QJsonValue::toArray() const
822{
823 return toArray(QJsonArray());
824}
825
826/*!
827 Converts the value to an object and returns it.
828
829 If type() is not Object, the \a defaultValue will be returned.
830 */
831QJsonObject QJsonValue::toObject(const QJsonObject &defaultValue) const
832{
833 if (!isObject())
834 return defaultValue;
835 QCborContainerPrivate *dd = nullptr;
836 const auto container = QJsonPrivate::Value::container(value);
837 const auto n = QJsonPrivate::Value::valueHelper(value);
838 Q_ASSERT(n == -1 || container == nullptr);
839 if (n < 0)
840 dd = container;
841 return QJsonObject(dd);
842}
843
844/*!
845 \overload
846
847 Converts the value to an object and returns it.
848
849 If type() is not Object, the \l {QJsonObject::}{QJsonObject()} will be returned.
850*/
851QJsonObject QJsonValue::toObject() const
852{
853 return toObject(QJsonObject());
854}
855
856/*!
857 Returns a QJsonValue representing the value for the key \a key.
858
859 Equivalent to calling toObject().value(key).
860
861 The returned QJsonValue is QJsonValue::Undefined if the key does not exist,
862 or if isObject() is false.
863
864 \since 5.10
865
866 \sa QJsonValue, QJsonValue::isUndefined(), QJsonObject
867 */
868const QJsonValue QJsonValue::operator[](const QString &key) const
869{
870 return (*this)[QStringView(key)];
871}
872
873/*!
874 \overload
875 \since 5.14
876*/
877const QJsonValue QJsonValue::operator[](QStringView key) const
878{
879 if (!isObject())
880 return QJsonValue(QJsonValue::Undefined);
881
882 return toObject().value(key);
883}
884
885/*!
886 \overload
887 \since 5.10
888*/
889const QJsonValue QJsonValue::operator[](QLatin1StringView key) const
890{
891 if (!isObject())
892 return QJsonValue(QJsonValue::Undefined);
893
894 return toObject().value(key);
895}
896
897/*!
898 Returns a QJsonValue representing the value for index \a i.
899
900 Equivalent to calling toArray().at(i).
901
902 The returned QJsonValue is QJsonValue::Undefined, if \a i is out of bounds,
903 or if isArray() is false.
904
905 \since 5.10
906
907 \sa QJsonValue, QJsonValue::isUndefined(), QJsonArray
908 */
909const QJsonValue QJsonValue::operator[](qsizetype i) const
910{
911 if (!isArray())
912 return QJsonValue(QJsonValue::Undefined);
913
914 return toArray().at(i);
915}
916
917/*!
918 \fn bool QJsonValue::operator==(const QJsonValue &lhs, const QJsonValue &rhs)
919
920 Returns \c true if the \a lhs value is equal to \a rhs value, \c false otherwise.
921*/
922bool comparesEqual(const QJsonValue &lhs, const QJsonValue &rhs)
923{
924 if (lhs.value.type() != rhs.value.type()) {
925 if (lhs.isDouble() && rhs.isDouble()) {
926 // One value Cbor integer, one Cbor double, should interact as doubles.
927 return lhs.toDouble() == rhs.toDouble();
928 }
929 return false;
930 }
931
932 switch (lhs.value.type()) {
933 case QCborValue::Undefined:
934 case QCborValue::Null:
935 case QCborValue::True:
936 case QCborValue::False:
937 break;
938 case QCborValue::Double:
939 return lhs.toDouble() == rhs.toDouble();
940 case QCborValue::Integer:
941 return QJsonPrivate::Value::valueHelper(lhs.value)
942 == QJsonPrivate::Value::valueHelper(rhs.value);
943 case QCborValue::String:
944 return lhs.toString() == rhs.toString();
945 case QCborValue::Array:
946 return lhs.toArray() == rhs.toArray();
947 case QCborValue::Map:
948 return lhs.toObject() == rhs.toObject();
949 default:
950 return false;
951 }
952 return true;
953}
954
955/*!
956 \fn bool QJsonValue::operator!=(const QJsonValue &lhs, const QJsonValue &rhs)
957
958 Returns \c true if the \a lhs value is not equal to \a rhs value, \c false otherwise.
959*/
960
961/*!
962 \class QJsonValueRef
963 \inmodule QtCore
964 \reentrant
965 \brief The QJsonValueRef class is a helper class for QJsonValue.
966
967 \internal
968
969 \ingroup json
970
971 When you get an object of type QJsonValueRef, if you can assign to it,
972 the assignment will apply to the character in the string from
973 which you got the reference. That is its whole purpose in life.
974
975 You can use it exactly in the same way as a reference to a QJsonValue.
976
977 The QJsonValueRef becomes invalid once modifications are made to the
978 string: if you want to keep the character, copy it into a QJsonValue.
979
980 Most of the QJsonValue member functions also exist in QJsonValueRef.
981 However, they are not explicitly documented here.
982*/
983
984void QJsonValueRef::detach()
985{
986#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
987 QCborContainerPrivate *d = QJsonPrivate::Value::container(*this);
988 d = QCborContainerPrivate::detach(d, d->elements.size());
989
990 if (is_object)
991 o->o.reset(d);
992 else
993 a->a.reset(d);
994#else
995 d = QCborContainerPrivate::detach(d, d->elements.size());
996#endif
997}
998
999static QJsonValueRef &assignToRef(QJsonValueRef &ref, const QCborValue &value, bool is_object)
1000{
1001 QCborContainerPrivate *d = QJsonPrivate::Value::container(ref);
1002 qsizetype index = QJsonPrivate::Value::indexHelper(ref);
1003 if (is_object && value.isUndefined()) {
1004 d->removeAt(index);
1005 d->removeAt(index - 1);
1006 } else {
1007 d->replaceAt(index, value);
1008 }
1009
1010 return ref;
1011}
1012
1013QJsonValueRef &QJsonValueRef::operator =(const QJsonValue &val)
1014{
1015 detach();
1016 return assignToRef(*this, QCborValue::fromJsonValue(val), is_object);
1017}
1018
1019QJsonValueRef &QJsonValueRef::operator =(const QJsonValueRef &ref)
1020{
1021 // ### optimize more?
1022 const QCborContainerPrivate *d = QJsonPrivate::Value::container(ref);
1023 qsizetype index = QJsonPrivate::Value::indexHelper(ref);
1024
1025 if (d == QJsonPrivate::Value::container(*this) &&
1026 index == QJsonPrivate::Value::indexHelper(*this))
1027 return *this; // self assignment
1028
1029 detach();
1030 return assignToRef(*this, d->valueAt(index), is_object);
1031}
1032
1033#ifndef QT_NO_VARIANT
1034QVariant QJsonValueConstRef::toVariant() const
1035{
1036 return concrete(*this).toVariant();
1037}
1038#endif // !QT_NO_VARIANT
1039
1040QJsonArray QJsonValueConstRef::toArray() const
1041{
1042 return concrete(*this).toArray();
1043}
1044
1045QJsonObject QJsonValueConstRef::toObject() const
1046{
1047 return concrete(*this).toObject();
1048}
1049
1050QJsonValue::Type QJsonValueConstRef::concreteType(QJsonValueConstRef self) noexcept
1051{
1052 return convertFromCborType(QJsonPrivate::Value::elementHelper(self).type);
1053}
1054
1055bool QJsonValueConstRef::concreteBool(QJsonValueConstRef self, bool defaultValue) noexcept
1056{
1057 auto &e = QJsonPrivate::Value::elementHelper(self);
1058 if (e.type == QCborValue::False)
1059 return false;
1060 if (e.type == QCborValue::True)
1061 return true;
1062 return defaultValue;
1063}
1064
1065qint64 QJsonValueConstRef::concreteInt(QJsonValueConstRef self, qint64 defaultValue, bool clamp) noexcept
1066{
1067 auto &e = QJsonPrivate::Value::elementHelper(self);
1068 qint64 v = defaultValue;
1069 if (e.type == QCborValue::Double) {
1070 // convertDoubleTo modifies the output even on returning false
1071 if (!convertDoubleTo<qint64>(e.fpvalue(), &v))
1072 v = defaultValue;
1073 } else if (e.type == QCborValue::Integer) {
1074 v = e.value;
1075 }
1076 if (clamp && qint64(int(v)) != v)
1077 return defaultValue;
1078 return v;
1079}
1080
1081double QJsonValueConstRef::concreteDouble(QJsonValueConstRef self, double defaultValue) noexcept
1082{
1083 auto &e = QJsonPrivate::Value::elementHelper(self);
1084 if (e.type == QCborValue::Double)
1085 return e.fpvalue();
1086 if (e.type == QCborValue::Integer)
1087 return e.value;
1088 return defaultValue;
1089}
1090
1091QString QJsonValueConstRef::concreteString(QJsonValueConstRef self, const QString &defaultValue)
1092{
1094 qsizetype index = QJsonPrivate::Value::indexHelper(self);
1095 if (d->elements.at(index).type != QCborValue::String)
1096 return defaultValue;
1097 return d->stringAt(index);
1098}
1099
1100QAnyStringView QJsonValueConstRef::concreteStringView(QJsonValueConstRef self, QAnyStringView defaultValue)
1101{
1103 const qsizetype index = QJsonPrivate::Value::indexHelper(self);
1104 if (d->elements.at(index).type != QCborValue::String)
1105 return defaultValue;
1106 return d->anyStringViewAt(index);
1107}
1108
1109QJsonValue QJsonValueConstRef::concrete(QJsonValueConstRef self) noexcept
1110{
1112 qsizetype index = QJsonPrivate::Value::indexHelper(self);
1113 return QJsonPrivate::Value::fromTrustedCbor(d->valueAt(index));
1114}
1115
1116QAnyStringView QJsonValueConstRef::objectKeyView(QJsonValueConstRef self)
1117{
1118 Q_ASSERT(self.is_object);
1120 const qsizetype index = QJsonPrivate::Value::indexHelper(self);
1121
1122 Q_ASSERT(d);
1123 Q_ASSERT(index < d->elements.size());
1124 return d->anyStringViewAt(index - 1);
1125}
1126
1128{
1129 Q_ASSERT(self.is_object);
1131 qsizetype index = QJsonPrivate::Value::indexHelper(self);
1132
1133 Q_ASSERT(d);
1134 Q_ASSERT(index < d->elements.size());
1135 return d->stringAt(index - 1);
1136}
1137
1138#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
1139QVariant QJsonValueRef::toVariant() const
1140{
1141 return QJsonValueConstRef::toVariant();
1142}
1143
1144QJsonArray QJsonValueRef::toArray() const
1145{
1146 return QJsonValueConstRef::toArray();
1147}
1148
1149QJsonObject QJsonValueRef::toObject() const
1150{
1151 return QJsonValueConstRef::toObject();
1152}
1153
1154QJsonValue QJsonValueRef::toValue() const
1155{
1156 return concrete(*this);
1157}
1158#else
1159QJsonValueRef QJsonValueRef::operator[](qsizetype key)
1160{
1161 if (d->elements.at(index).type != QCborValue::Array)
1162 d->replaceAt(index, QCborValue::Array);
1163
1164 auto &e = d->elements[index];
1165 e.container = QCborContainerPrivate::grow(e.container, key); // detaches
1166 e.flags |= QtCbor::Element::IsContainer;
1167
1168 return QJsonValueRef(e.container, key, false);
1169}
1170
1171QJsonValueRef QJsonValueRef::operator[](QAnyStringView key)
1172{
1173 // must go through QJsonObject because some of the machinery is non-static
1174 // member or file-static in qjsonobject.cpp
1175 QJsonObject o = QJsonPrivate::Value::fromTrustedCbor(d->valueAt(index)).toObject();
1176 QJsonValueRef ret = key.visit([&](auto v) {
1177 if constexpr (std::is_same_v<decltype(v), QUtf8StringView>)
1178 return o[QString::fromUtf8(v)];
1179 else
1180 return o[v];
1181 });
1182
1183 // ### did the QJsonObject::operator[] above detach?
1184 QCborContainerPrivate *x = o.o.take();
1185 Q_ASSERT(x->ref.loadRelaxed() == 1);
1186
1187 auto &e = d->elements[index];
1188 if (e.flags & QtCbor::Element::IsContainer && e.container != x)
1189 o.o.reset(e.container); // might not an object!
1190
1191 e.flags |= QtCbor::Element::IsContainer;
1192 e.container = x;
1193
1194 return ret;
1195}
1196#endif
1197
1198size_t qHash(const QJsonValue &value, size_t seed)
1199{
1200 switch (value.type()) {
1201 case QJsonValue::Null:
1202 return qHash(nullptr, seed);
1203 case QJsonValue::Bool:
1204 return qHash(value.toBool(), seed);
1205 case QJsonValue::Double:
1206 return qHash(value.toDouble(), seed);
1207 case QJsonValue::String:
1208 return qHash(value.toString(), seed);
1209 case QJsonValue::Array:
1210 return qHash(value.toArray(), seed);
1211 case QJsonValue::Object:
1212 return qHash(value.toObject(), seed);
1213 case QJsonValue::Undefined:
1214 return seed;
1215 }
1216 Q_UNREACHABLE_RETURN(0);
1217}
1218
1219#if !defined(QT_NO_DEBUG_STREAM)
1220QDebug operator<<(QDebug dbg, const QJsonValue &o)
1221{
1222 QDebugStateSaver saver(dbg);
1223 switch (o.value.type()) {
1224 case QCborValue::Undefined:
1225 dbg << "QJsonValue(undefined)";
1226 break;
1227 case QCborValue::Null:
1228 dbg << "QJsonValue(null)";
1229 break;
1230 case QCborValue::True:
1231 case QCborValue::False:
1232 dbg.nospace() << "QJsonValue(bool, " << o.toBool() << ')';
1233 break;
1234 case QCborValue::Integer:
1235 dbg.nospace() << "QJsonValue(double, " << o.toInteger() << ')';
1236 break;
1237 case QCborValue::Double:
1238 dbg.nospace() << "QJsonValue(double, " << o.toDouble() << ')';
1239 break;
1240 case QCborValue::String:
1241 dbg.nospace() << "QJsonValue(string, " << o.toString() << ')';
1242 break;
1243 case QCborValue::Array:
1244 dbg.nospace() << "QJsonValue(array, ";
1245 dbg << o.toArray();
1246 dbg << ')';
1247 break;
1248 case QCborValue::Map:
1249 dbg.nospace() << "QJsonValue(object, ";
1250 dbg << o.toObject();
1251 dbg << ')';
1252 break;
1253 default:
1254 Q_UNREACHABLE();
1255 }
1256 return dbg;
1257}
1258#endif
1259
1260#ifndef QT_NO_DATASTREAM
1261QDataStream &operator<<(QDataStream &stream, const QJsonValue &v)
1262{
1263 quint8 type = v.type();
1264 stream << type;
1265 switch (type) {
1266 case QJsonValue::Undefined:
1267 case QJsonValue::Null:
1268 break;
1269 case QJsonValue::Bool:
1270 stream << v.toBool();
1271 break;
1272 case QJsonValue::Double:
1273 stream << v.toDouble();
1274 break;
1275 case QJsonValue::String:
1276 stream << v.toString();
1277 break;
1278 case QJsonValue::Array:
1279 stream << v.toArray();
1280 break;
1281 case QJsonValue::Object:
1282 stream << v.toObject();
1283 break;
1284 }
1285 return stream;
1286}
1287
1288QDataStream &operator>>(QDataStream &stream, QJsonValue &v)
1289{
1290 quint8 type;
1291 stream >> type;
1292 switch (type) {
1293 case QJsonValue::Undefined:
1294 case QJsonValue::Null:
1295 v = QJsonValue{QJsonValue::Type(type)};
1296 break;
1297 case QJsonValue::Bool: {
1298 bool b;
1299 stream >> b;
1300 v = QJsonValue(b);
1301 break;
1302 } case QJsonValue::Double: {
1303 double d;
1304 stream >> d;
1305 v = QJsonValue{d};
1306 break;
1307 } case QJsonValue::String: {
1308 QString s;
1309 stream >> s;
1310 v = QJsonValue{s};
1311 break;
1312 }
1313 case QJsonValue::Array: {
1314 QJsonArray a;
1315 stream >> a;
1316 v = QJsonValue{a};
1317 break;
1318 }
1319 case QJsonValue::Object: {
1320 QJsonObject o;
1321 stream >> o;
1322 v = QJsonValue{o};
1323 break;
1324 }
1325 default: {
1326 stream.setStatus(QDataStream::ReadCorruptData);
1327 v = QJsonValue{QJsonValue::Undefined};
1328 }
1329 }
1330 return stream;
1331}
1332#endif
1333
1334QT_END_NAMESPACE
static const QCborContainerPrivate * container(QJsonValueConstRef r) noexcept
Definition qjson_p.h:177
QDataStream & operator>>(QDataStream &stream, QJsonValue &v)
static QJsonValueRef & assignToRef(QJsonValueRef &ref, const QCborValue &value, bool is_object)
static QCborValue doubleValueHelper(double v)
static QT_BEGIN_NAMESPACE QJsonValue::Type convertFromCborType(QCborValue::Type type) noexcept
bool comparesEqual(const QJsonValue &lhs, const QJsonValue &rhs)
size_t qHash(const QJsonValue &value, size_t seed)