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
275/*!
276 \fn QJsonValue::QJsonValue(QJsonValue &&other)
277 \since 5.10
278
279 Move-constructs a QJsonValue from \a other.
280*/
281
282/*!
283 \fn QJsonValue &QJsonValue::operator =(QJsonValue &&other)
284 \since 5.10
285
286 Move-assigns \a other to this value.
287*/
288
289/*!
290 \fn void QJsonValue::swap(QJsonValue &other)
291 \since 5.10
292 \memberswap{value}
293*/
294
295/*!
296 \fn bool QJsonValue::isNull() const
297
298 Returns \c true if the value is null.
299*/
300
301/*!
302 \fn bool QJsonValue::isBool() const
303
304 Returns \c true if the value contains a boolean.
305
306 \sa toBool()
307 */
308
309/*!
310 \fn bool QJsonValue::isDouble() const
311
312 Returns \c true if the value contains a double.
313
314 \sa toDouble()
315 */
316
317/*!
318 \fn bool QJsonValue::isString() const
319
320 Returns \c true if the value contains a string.
321
322 \sa toString()
323 */
324
325/*!
326 \fn bool QJsonValue::isArray() const
327
328 Returns \c true if the value contains an array.
329
330 \sa toArray()
331 */
332
333/*!
334 \fn bool QJsonValue::isObject() const
335
336 Returns \c true if the value contains an object.
337
338 \sa toObject()
339 */
340
341/*!
342 \fn bool QJsonValue::isUndefined() const
343
344 Returns \c true if the value is undefined. This can happen in certain
345 error cases as e.g. accessing a non existing key in a QJsonObject.
346 */
347
348#ifndef QT_NO_VARIANT
349/*!
350 Converts \a variant to a QJsonValue and returns it.
351
352 The conversion will convert QVariant types as follows:
353
354 \table
355 \header
356 \li Source type
357 \li Destination type
358 \row
359 \li
360 \list
361 \li QMetaType::Nullptr
362 \endlist
363 \li QJsonValue::Null
364 \row
365 \li
366 \list
367 \li QMetaType::Bool
368 \endlist
369 \li QJsonValue::Bool
370 \row
371 \li
372 \list
373 \li QMetaType::Int
374 \li QMetaType::UInt
375 \li QMetaType::LongLong
376 \li QMetaType::ULongLong
377 \li QMetaType::Float
378 \li QMetaType::Double
379 \endlist
380 \li QJsonValue::Double
381 \row
382 \li
383 \list
384 \li QMetaType::QString
385 \endlist
386 \li QJsonValue::String
387 \row
388 \li
389 \list
390 \li QMetaType::QStringList
391 \li QMetaType::QVariantList
392 \endlist
393 \li QJsonValue::Array
394 \row
395 \li
396 \list
397 \li QMetaType::QVariantMap
398 \li QMetaType::QVariantHash
399 \endlist
400 \li QJsonValue::Object
401
402 \row
403 \li
404 \list
405 \li QMetaType::QUrl
406 \endlist
407 \li QJsonValue::String. The conversion will use QUrl::toString() with flag
408 QUrl::FullyEncoded, so as to ensure maximum compatibility in parsing the URL
409 \row
410 \li
411 \list
412 \li QMetaType::QUuid
413 \endlist
414 \li QJsonValue::String. Since Qt 5.11, the resulting string will not include braces
415 \row
416 \li
417 \list
418 \li QMetaType::QCborValue
419 \endlist
420 \li Whichever type QCborValue::toJsonValue() returns.
421 \row
422 \li
423 \list
424 \li QMetaType::QCborArray
425 \endlist
426 \li QJsonValue::Array. See QCborValue::toJsonValue() for conversion restrictions.
427 \row
428 \li
429 \list
430 \li QMetaType::QCborMap
431 \endlist
432 \li QJsonValue::Map. See QCborValue::toJsonValue() for conversion restrictions and the
433 "stringification" of map keys.
434 \endtable
435
436 \section2 Loss of information and other types
437
438 QVariant can carry more information than is representable in JSON. If the
439 QVariant is not one of the types above, the conversion is not guaranteed
440 and is subject to change in future versions of Qt, as the UUID one did.
441 Code should strive not to use any other types than those listed above.
442
443 If QVariant::isNull() returns true, a null QJsonValue is returned or
444 inserted into the list or object, regardless of the type carried by
445 QVariant. Note the behavior change in Qt 6.0 affecting QVariant::isNull()
446 also affects this function.
447
448 A floating point value that is either an infinity or NaN will be converted
449 to a null JSON value. Since Qt 6.0, QJsonValue can store the full precision
450 of any 64-bit signed integer without loss, but in previous versions values
451 outside the range of ±2^53 may lose precision. Unsigned 64-bit values
452 greater than or equal to 2^63 will either lose precision or alias to
453 negative values, so QMetaType::ULongLong should be avoided.
454
455 For other types not listed above, a conversion to string will be attempted,
456 usually but not always by calling QVariant::toString(). If the conversion
457 fails the value is replaced by a null JSON value. Note that
458 QVariant::toString() is also lossy for the majority of types. For example,
459 if the passed QVariant is representing raw byte array data, it is recommended
460 to pre-encode it to \l {RFC 4686}{Base64} (or
461 another lossless encoding), otherwise a lossy conversion using QString::fromUtf8()
462 will be used.
463
464 Please note that the conversions via QVariant::toString() are subject to
465 change at any time. Both QVariant and QJsonValue may be extended in the
466 future to support more types, which will result in a change in how this
467 function performs conversions.
468
469 \sa toVariant(), QCborValue::fromVariant()
470 */
471QJsonValue QJsonValue::fromVariant(const QVariant &variant)
472{
473 switch (variant.metaType().id()) {
474 case QMetaType::Nullptr:
475 return QJsonValue(Null);
476 case QMetaType::Bool:
477 return QJsonValue(variant.toBool());
478 case QMetaType::Short:
479 case QMetaType::UShort:
480 case QMetaType::Int:
481 case QMetaType::UInt:
482 case QMetaType::Long:
483 case QMetaType::LongLong:
484 return QJsonValue(variant.toLongLong());
485 case QMetaType::ULong:
486 case QMetaType::ULongLong:
487 if (variant.toULongLong() <= static_cast<uint64_t>(std::numeric_limits<qint64>::max()))
488 return QJsonValue(variant.toLongLong());
489 Q_FALLTHROUGH();
490 case QMetaType::Float16:
491 case QMetaType::Float:
492 case QMetaType::Double: {
493 double v = variant.toDouble();
494 return qt_is_finite(v) ? QJsonValue(v) : QJsonValue();
495 }
496 case QMetaType::QString:
497 return QJsonValue(variant.toString());
498 case QMetaType::QStringList:
499 return QJsonValue(QJsonArray::fromStringList(variant.toStringList()));
500 case QMetaType::QVariantList:
501 return QJsonValue(QJsonArray::fromVariantList(variant.toList()));
502 case QMetaType::QVariantMap:
503 return QJsonValue(QJsonObject::fromVariantMap(variant.toMap()));
504 case QMetaType::QVariantHash:
505 return QJsonValue(QJsonObject::fromVariantHash(variant.toHash()));
506#ifndef QT_BOOTSTRAPPED
507 case QMetaType::QUrl:
508 return QJsonValue(variant.toUrl().toString(QUrl::FullyEncoded));
509 case QMetaType::QUuid:
510 return variant.toUuid().toString(QUuid::WithoutBraces);
511 case QMetaType::QJsonValue:
512 return variant.toJsonValue();
513 case QMetaType::QJsonObject:
514 return variant.toJsonObject();
515 case QMetaType::QJsonArray:
516 return variant.toJsonArray();
517 case QMetaType::QJsonDocument: {
518 QJsonDocument doc = variant.toJsonDocument();
519 return doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object());
520 }
521 case QMetaType::QCborValue:
522 return qvariant_cast<QCborValue>(variant).toJsonValue();
523 case QMetaType::QCborArray:
524 return qvariant_cast<QCborArray>(variant).toJsonArray();
525 case QMetaType::QCborMap:
526 return qvariant_cast<QCborMap>(variant).toJsonObject();
527#endif
528 default:
529 break;
530 }
531 QString string = variant.toString();
532 if (string.isEmpty())
533 return QJsonValue();
534 return QJsonValue(string);
535}
536
537/*!
538 Converts the value to a \l {QVariant::}{QVariant()}.
539
540 The QJsonValue types will be converted as follows:
541
542 \value Null QMetaType::Nullptr
543 \value Bool QMetaType::Bool
544 \value Double QMetaType::Double or QMetaType::LongLong
545 \value String QString
546 \value Array QVariantList
547 \value Object QVariantMap
548 \value Undefined \l {QVariant::}{QVariant()}
549
550 \sa fromVariant()
551 */
552QVariant QJsonValue::toVariant() const
553{
554 switch (value.type()) {
555 case QCborValue::True:
556 return true;
557 case QCborValue::False:
558 return false;
559 case QCborValue::Integer:
560 return toInteger();
561 case QCborValue::Double:
562 return toDouble();
563 case QCborValue::String:
564 return toString();
565 case QCborValue::Array:
566 return toArray().toVariantList();
567 case QCborValue::Map:
568 return toObject().toVariantMap();
569 case QCborValue::Null:
570 return QVariant::fromValue(nullptr);
571 case QCborValue::Undefined:
572 default:
573 break;
574 }
575 return QVariant();
576}
577
578/*!
579 \enum QJsonValue::Type
580
581 This enum describes the type of the JSON value.
582
583 \value Null A Null value
584 \value Bool A boolean value. Use toBool() to convert to a bool.
585 \value Double A number value. Use toDouble() to convert to a double,
586 or toInteger() to convert to a qint64.
587 \value String A string. Use toString() to convert to a QString.
588 \value Array An array. Use toArray() to convert to a QJsonArray.
589 \value Object An object. Use toObject() to convert to a QJsonObject.
590 \value Undefined The value is undefined. This is usually returned as an
591 error condition, when trying to read an out of bounds value
592 in an array or a non existent key in an object.
593*/
594#endif // !QT_NO_VARIANT
595
596/*!
597 \since 6.9
598 Parses \a json as a UTF-8 encoded JSON value, and creates a QJsonValue
599 from it.
600
601 Returns a valid QJsonValue if the parsing succeeds. If it fails, the
602 returned value will be \l {QJsonValue::isUndefined} {undefined}, and
603 the optional \a error variable will contain further details about the
604 error.
605
606 \sa QJsonParseError, isUndefined(), toJson()
607 */
608QJsonValue QJsonValue::fromJson(QByteArrayView json, QJsonParseError *error)
609{
610 QJsonPrivate::Parser parser(json);
611 QJsonValue result;
612 result.value = parser.parse(error);
613 return result;
614}
615
616/*!
617\if defined(qt7)
618 \enum QJsonValue::JsonFormat
619 \since 6.9
620
621 This value defines the format of the JSON byte array produced
622 when converting to a QJsonValue using toJson().
623
624 \value Indented Defines human readable output as follows:
625 \snippet code/src_corelib_serialization_qjsondocument.cpp 0
626
627 \value Compact Defines a compact output as follows:
628 \snippet code/src_corelib_serialization_qjsondocument.cpp 1
629\else
630 \typealias QJsonValue::JsonFormat
631 \since 6.9
632
633 Same as \l QJsonDocument::JsonFormat.
634\endif
635*/
636
637/*!
638 \since 6.9
639 Converts the QJsonValue to a UTF-8 encoded JSON value in the provided \a format.
640
641 \sa fromJson(), JsonFormat
642 */
643QByteArray QJsonValue::toJson(JsonFormat format) const
644{
645 QByteArray json;
646
647 QJsonPrivate::Writer::valueToJson(value, json, 0, (format == JsonFormat::Compact));
648
649 return json;
650}
651
652/*!
653 Returns the type of the value.
654
655 \sa QJsonValue::Type
656 */
657QJsonValue::Type QJsonValue::type() const
658{
659 return convertFromCborType(value.type());
660}
661
662/*!
663 Converts the value to a bool and returns it.
664
665 If type() is not bool, the \a defaultValue will be returned.
666 */
667bool QJsonValue::toBool(bool defaultValue) const
668{
669 switch (value.type()) {
670 case QCborValue::True:
671 return true;
672 case QCborValue::False:
673 return false;
674 default:
675 return defaultValue;
676 }
677}
678
679/*!
680 \since 5.2
681 Converts the value to an int and returns it.
682
683 If type() is not Double or the value is not a whole number,
684 the \a defaultValue will be returned.
685 */
686int QJsonValue::toInt(int defaultValue) const
687{
688 switch (value.type()) {
689 case QCborValue::Double: {
690 int dblInt;
691 if (convertDoubleTo<int>(toDouble(), &dblInt))
692 return dblInt;
693 break;
694 }
695 case QCborValue::Integer: {
696 const auto n = value.toInteger();
697 if (qint64(int(n)) == n)
698 return int(n);
699 break;
700 }
701 default:
702 break;
703 }
704 return defaultValue;
705}
706
707/*!
708 \since 6.0
709 Converts the value to an integer and returns it.
710
711 If type() is not Double or the value is not a whole number
712 representable as qint64, the \a defaultValue will be returned.
713 */
714qint64 QJsonValue::toInteger(qint64 defaultValue) const
715{
716 switch (value.type()) {
717 case QCborValue::Integer:
718 return value.toInteger();
719 case QCborValue::Double: {
720 qint64 dblInt;
721 if (convertDoubleTo<qint64>(toDouble(), &dblInt))
722 return dblInt;
723 break;
724 }
725 default:
726 break;
727 }
728 return defaultValue;
729}
730
731/*!
732 Converts the value to a double and returns it.
733
734 If type() is not Double, the \a defaultValue will be returned.
735 */
736double QJsonValue::toDouble(double defaultValue) const
737{
738 return value.toDouble(defaultValue);
739}
740
741/*!
742 Converts the value to a QString and returns it.
743
744 If type() is not String, the \a defaultValue will be returned.
745
746 \sa toStringView()
747 */
748QString QJsonValue::toString(const QString &defaultValue) const
749{
750 return value.toString(defaultValue);
751}
752
753/*!
754 \since 6.10
755
756 Returns the string value stored in this QJsonValue, if it is of the
757 \l{String}{string} type. Otherwise, it returns \a defaultValue. Since
758 QJsonValue stores strings in either US-ASCII, UTF-8 or UTF-16, the returned
759 QAnyStringView may be in any of these encodings.
760
761 This function does not allocate memory. The return value is valid until the
762 next call to a non-const member function on this object. If this object goes
763 out of scope, the return value is valid until the next call to a non-const
764 member function on the parent JSON object or array.
765
766 \sa toString()
767*/
768QAnyStringView QJsonValue::toStringView(QAnyStringView defaultValue) const
769{
770 return value.toStringView(defaultValue);
771}
772
773/*!
774 Converts the value to a QString and returns it.
775
776 If type() is not String, a null QString will be returned.
777
778 \sa QString::isNull()
779 */
780QString QJsonValue::toString() const
781{
782 return value.toString();
783}
784
785/*!
786 Converts the value to an array and returns it.
787
788 If type() is not Array, the \a defaultValue will be returned.
789 */
790QJsonArray QJsonValue::toArray(const QJsonArray &defaultValue) const
791{
792 if (!isArray())
793 return defaultValue;
794 QCborContainerPrivate *dd = nullptr;
795 const auto n = QJsonPrivate::Value::valueHelper(value);
796 const auto container = QJsonPrivate::Value::container(value);
797 Q_ASSERT(n == -1 || container == nullptr);
798 if (n < 0)
799 dd = container;
800 return QJsonArray(dd);
801}
802
803/*!
804 \overload
805
806 Converts the value to an array and returns it.
807
808 If type() is not Array, a \l{QJsonArray::}{QJsonArray()} will be returned.
809 */
810QJsonArray QJsonValue::toArray() const
811{
812 return toArray(QJsonArray());
813}
814
815/*!
816 Converts the value to an object and returns it.
817
818 If type() is not Object, the \a defaultValue will be returned.
819 */
820QJsonObject QJsonValue::toObject(const QJsonObject &defaultValue) const
821{
822 if (!isObject())
823 return defaultValue;
824 QCborContainerPrivate *dd = nullptr;
825 const auto container = QJsonPrivate::Value::container(value);
826 const auto n = QJsonPrivate::Value::valueHelper(value);
827 Q_ASSERT(n == -1 || container == nullptr);
828 if (n < 0)
829 dd = container;
830 return QJsonObject(dd);
831}
832
833/*!
834 \overload
835
836 Converts the value to an object and returns it.
837
838 If type() is not Object, the \l {QJsonObject::}{QJsonObject()} will be returned.
839*/
840QJsonObject QJsonValue::toObject() const
841{
842 return toObject(QJsonObject());
843}
844
845/*!
846 Returns a QJsonValue representing the value for the key \a key.
847
848 Equivalent to calling toObject().value(key).
849
850 The returned QJsonValue is QJsonValue::Undefined if the key does not exist,
851 or if isObject() is false.
852
853 \since 5.10
854
855 \sa QJsonValue, QJsonValue::isUndefined(), QJsonObject
856 */
857const QJsonValue QJsonValue::operator[](const QString &key) const
858{
859 return (*this)[QStringView(key)];
860}
861
862/*!
863 \overload
864 \since 5.14
865*/
866const QJsonValue QJsonValue::operator[](QStringView key) const
867{
868 if (!isObject())
869 return QJsonValue(QJsonValue::Undefined);
870
871 return toObject().value(key);
872}
873
874/*!
875 \overload
876 \since 5.10
877*/
878const QJsonValue QJsonValue::operator[](QLatin1StringView key) const
879{
880 if (!isObject())
881 return QJsonValue(QJsonValue::Undefined);
882
883 return toObject().value(key);
884}
885
886/*!
887 Returns a QJsonValue representing the value for index \a i.
888
889 Equivalent to calling toArray().at(i).
890
891 The returned QJsonValue is QJsonValue::Undefined, if \a i is out of bounds,
892 or if isArray() is false.
893
894 \since 5.10
895
896 \sa QJsonValue, QJsonValue::isUndefined(), QJsonArray
897 */
898const QJsonValue QJsonValue::operator[](qsizetype i) const
899{
900 if (!isArray())
901 return QJsonValue(QJsonValue::Undefined);
902
903 return toArray().at(i);
904}
905
906/*!
907 \fn bool QJsonValue::operator==(const QJsonValue &lhs, const QJsonValue &rhs)
908
909 Returns \c true if the \a lhs value is equal to \a rhs value, \c false otherwise.
910*/
911bool comparesEqual(const QJsonValue &lhs, const QJsonValue &rhs)
912{
913 if (lhs.value.type() != rhs.value.type()) {
914 if (lhs.isDouble() && rhs.isDouble()) {
915 // One value Cbor integer, one Cbor double, should interact as doubles.
916 return lhs.toDouble() == rhs.toDouble();
917 }
918 return false;
919 }
920
921 switch (lhs.value.type()) {
922 case QCborValue::Undefined:
923 case QCborValue::Null:
924 case QCborValue::True:
925 case QCborValue::False:
926 break;
927 case QCborValue::Double:
928 return lhs.toDouble() == rhs.toDouble();
929 case QCborValue::Integer:
930 return QJsonPrivate::Value::valueHelper(lhs.value)
931 == QJsonPrivate::Value::valueHelper(rhs.value);
932 case QCborValue::String:
933 return lhs.toString() == rhs.toString();
934 case QCborValue::Array:
935 return lhs.toArray() == rhs.toArray();
936 case QCborValue::Map:
937 return lhs.toObject() == rhs.toObject();
938 default:
939 return false;
940 }
941 return true;
942}
943
944/*!
945 \fn bool QJsonValue::operator!=(const QJsonValue &lhs, const QJsonValue &rhs)
946
947 Returns \c true if the \a lhs value is not equal to \a rhs value, \c false otherwise.
948*/
949
950/*!
951 \class QJsonValueRef
952 \inmodule QtCore
953 \reentrant
954 \brief The QJsonValueRef class is a helper class for QJsonValue.
955
956 \internal
957
958 \ingroup json
959
960 When you get an object of type QJsonValueRef, if you can assign to it,
961 the assignment will apply to the character in the string from
962 which you got the reference. That is its whole purpose in life.
963
964 You can use it exactly in the same way as a reference to a QJsonValue.
965
966 The QJsonValueRef becomes invalid once modifications are made to the
967 string: if you want to keep the character, copy it into a QJsonValue.
968
969 Most of the QJsonValue member functions also exist in QJsonValueRef.
970 However, they are not explicitly documented here.
971*/
972
973void QJsonValueRef::detach()
974{
975#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
976 QCborContainerPrivate *d = QJsonPrivate::Value::container(*this);
977 d = QCborContainerPrivate::detach(d, d->elements.size());
978
979 if (is_object)
980 o->o.reset(d);
981 else
982 a->a.reset(d);
983#else
984 d = QCborContainerPrivate::detach(d, d->elements.size());
985#endif
986}
987
988static QJsonValueRef &assignToRef(QJsonValueRef &ref, const QCborValue &value, bool is_object)
989{
990 QCborContainerPrivate *d = QJsonPrivate::Value::container(ref);
991 qsizetype index = QJsonPrivate::Value::indexHelper(ref);
992 if (is_object && value.isUndefined()) {
993 d->removeAt(index);
994 d->removeAt(index - 1);
995 } else {
996 d->replaceAt(index, value);
997 }
998
999 return ref;
1000}
1001
1002QJsonValueRef &QJsonValueRef::operator =(const QJsonValue &val)
1003{
1004 detach();
1005 return assignToRef(*this, QCborValue::fromJsonValue(val), is_object);
1006}
1007
1008QJsonValueRef &QJsonValueRef::operator =(const QJsonValueRef &ref)
1009{
1010 // ### optimize more?
1011 const QCborContainerPrivate *d = QJsonPrivate::Value::container(ref);
1012 qsizetype index = QJsonPrivate::Value::indexHelper(ref);
1013
1014 if (d == QJsonPrivate::Value::container(*this) &&
1015 index == QJsonPrivate::Value::indexHelper(*this))
1016 return *this; // self assignment
1017
1018 detach();
1019 return assignToRef(*this, d->valueAt(index), is_object);
1020}
1021
1022#ifndef QT_NO_VARIANT
1023QVariant QJsonValueConstRef::toVariant() const
1024{
1025 return concrete(*this).toVariant();
1026}
1027#endif // !QT_NO_VARIANT
1028
1029QJsonArray QJsonValueConstRef::toArray() const
1030{
1031 return concrete(*this).toArray();
1032}
1033
1034QJsonObject QJsonValueConstRef::toObject() const
1035{
1036 return concrete(*this).toObject();
1037}
1038
1039QJsonValue::Type QJsonValueConstRef::concreteType(QJsonValueConstRef self) noexcept
1040{
1041 return convertFromCborType(QJsonPrivate::Value::elementHelper(self).type);
1042}
1043
1044bool QJsonValueConstRef::concreteBool(QJsonValueConstRef self, bool defaultValue) noexcept
1045{
1046 auto &e = QJsonPrivate::Value::elementHelper(self);
1047 if (e.type == QCborValue::False)
1048 return false;
1049 if (e.type == QCborValue::True)
1050 return true;
1051 return defaultValue;
1052}
1053
1054qint64 QJsonValueConstRef::concreteInt(QJsonValueConstRef self, qint64 defaultValue, bool clamp) noexcept
1055{
1056 auto &e = QJsonPrivate::Value::elementHelper(self);
1057 qint64 v = defaultValue;
1058 if (e.type == QCborValue::Double) {
1059 // convertDoubleTo modifies the output even on returning false
1060 if (!convertDoubleTo<qint64>(e.fpvalue(), &v))
1061 v = defaultValue;
1062 } else if (e.type == QCborValue::Integer) {
1063 v = e.value;
1064 }
1065 if (clamp && qint64(int(v)) != v)
1066 return defaultValue;
1067 return v;
1068}
1069
1070double QJsonValueConstRef::concreteDouble(QJsonValueConstRef self, double defaultValue) noexcept
1071{
1072 auto &e = QJsonPrivate::Value::elementHelper(self);
1073 if (e.type == QCborValue::Double)
1074 return e.fpvalue();
1075 if (e.type == QCborValue::Integer)
1076 return e.value;
1077 return defaultValue;
1078}
1079
1080QString QJsonValueConstRef::concreteString(QJsonValueConstRef self, const QString &defaultValue)
1081{
1083 qsizetype index = QJsonPrivate::Value::indexHelper(self);
1084 if (d->elements.at(index).type != QCborValue::String)
1085 return defaultValue;
1086 return d->stringAt(index);
1087}
1088
1089QAnyStringView QJsonValueConstRef::concreteStringView(QJsonValueConstRef self, QAnyStringView defaultValue)
1090{
1092 const qsizetype index = QJsonPrivate::Value::indexHelper(self);
1093 if (d->elements.at(index).type != QCborValue::String)
1094 return defaultValue;
1095 return d->anyStringViewAt(index);
1096}
1097
1098QJsonValue QJsonValueConstRef::concrete(QJsonValueConstRef self) noexcept
1099{
1101 qsizetype index = QJsonPrivate::Value::indexHelper(self);
1102 return QJsonPrivate::Value::fromTrustedCbor(d->valueAt(index));
1103}
1104
1105QAnyStringView QJsonValueConstRef::objectKeyView(QJsonValueConstRef self)
1106{
1107 Q_ASSERT(self.is_object);
1109 const qsizetype index = QJsonPrivate::Value::indexHelper(self);
1110
1111 Q_ASSERT(d);
1112 Q_ASSERT(index < d->elements.size());
1113 return d->anyStringViewAt(index - 1);
1114}
1115
1117{
1118 Q_ASSERT(self.is_object);
1120 qsizetype index = QJsonPrivate::Value::indexHelper(self);
1121
1122 Q_ASSERT(d);
1123 Q_ASSERT(index < d->elements.size());
1124 return d->stringAt(index - 1);
1125}
1126
1127#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
1128QVariant QJsonValueRef::toVariant() const
1129{
1130 return QJsonValueConstRef::toVariant();
1131}
1132
1133QJsonArray QJsonValueRef::toArray() const
1134{
1135 return QJsonValueConstRef::toArray();
1136}
1137
1138QJsonObject QJsonValueRef::toObject() const
1139{
1140 return QJsonValueConstRef::toObject();
1141}
1142
1143QJsonValue QJsonValueRef::toValue() const
1144{
1145 return concrete(*this);
1146}
1147#else
1148QJsonValueRef QJsonValueRef::operator[](qsizetype key)
1149{
1150 if (d->elements.at(index).type != QCborValue::Array)
1151 d->replaceAt(index, QCborValue::Array);
1152
1153 auto &e = d->elements[index];
1154 e.container = QCborContainerPrivate::grow(e.container, key); // detaches
1155 e.flags |= QtCbor::Element::IsContainer;
1156
1157 return QJsonValueRef(e.container, key, false);
1158}
1159
1160QJsonValueRef QJsonValueRef::operator[](QAnyStringView key)
1161{
1162 // must go through QJsonObject because some of the machinery is non-static
1163 // member or file-static in qjsonobject.cpp
1164 QJsonObject o = QJsonPrivate::Value::fromTrustedCbor(d->valueAt(index)).toObject();
1165 QJsonValueRef ret = key.visit([&](auto v) {
1166 if constexpr (std::is_same_v<decltype(v), QUtf8StringView>)
1167 return o[QString::fromUtf8(v)];
1168 else
1169 return o[v];
1170 });
1171
1172 // ### did the QJsonObject::operator[] above detach?
1173 QCborContainerPrivate *x = o.o.take();
1174 Q_ASSERT(x->ref.loadRelaxed() == 1);
1175
1176 auto &e = d->elements[index];
1177 if (e.flags & QtCbor::Element::IsContainer && e.container != x)
1178 o.o.reset(e.container); // might not an object!
1179
1180 e.flags |= QtCbor::Element::IsContainer;
1181 e.container = x;
1182
1183 return ret;
1184}
1185#endif
1186
1187size_t qHash(const QJsonValue &value, size_t seed)
1188{
1189 switch (value.type()) {
1190 case QJsonValue::Null:
1191 return qHash(nullptr, seed);
1192 case QJsonValue::Bool:
1193 return qHash(value.toBool(), seed);
1194 case QJsonValue::Double:
1195 return qHash(value.toDouble(), seed);
1196 case QJsonValue::String:
1197 return qHash(value.toString(), seed);
1198 case QJsonValue::Array:
1199 return qHash(value.toArray(), seed);
1200 case QJsonValue::Object:
1201 return qHash(value.toObject(), seed);
1202 case QJsonValue::Undefined:
1203 return seed;
1204 }
1205 Q_UNREACHABLE_RETURN(0);
1206}
1207
1208#if !defined(QT_NO_DEBUG_STREAM)
1209QDebug operator<<(QDebug dbg, const QJsonValue &o)
1210{
1211 QDebugStateSaver saver(dbg);
1212 switch (o.value.type()) {
1213 case QCborValue::Undefined:
1214 dbg << "QJsonValue(undefined)";
1215 break;
1216 case QCborValue::Null:
1217 dbg << "QJsonValue(null)";
1218 break;
1219 case QCborValue::True:
1220 case QCborValue::False:
1221 dbg.nospace() << "QJsonValue(bool, " << o.toBool() << ')';
1222 break;
1223 case QCborValue::Integer:
1224 dbg.nospace() << "QJsonValue(double, " << o.toInteger() << ')';
1225 break;
1226 case QCborValue::Double:
1227 dbg.nospace() << "QJsonValue(double, " << o.toDouble() << ')';
1228 break;
1229 case QCborValue::String:
1230 dbg.nospace() << "QJsonValue(string, " << o.toString() << ')';
1231 break;
1232 case QCborValue::Array:
1233 dbg.nospace() << "QJsonValue(array, ";
1234 dbg << o.toArray();
1235 dbg << ')';
1236 break;
1237 case QCborValue::Map:
1238 dbg.nospace() << "QJsonValue(object, ";
1239 dbg << o.toObject();
1240 dbg << ')';
1241 break;
1242 default:
1243 Q_UNREACHABLE();
1244 }
1245 return dbg;
1246}
1247#endif
1248
1249#ifndef QT_NO_DATASTREAM
1250QDataStream &operator<<(QDataStream &stream, const QJsonValue &v)
1251{
1252 quint8 type = v.type();
1253 stream << type;
1254 switch (type) {
1255 case QJsonValue::Undefined:
1256 case QJsonValue::Null:
1257 break;
1258 case QJsonValue::Bool:
1259 stream << v.toBool();
1260 break;
1261 case QJsonValue::Double:
1262 stream << v.toDouble();
1263 break;
1264 case QJsonValue::String:
1265 stream << v.toString();
1266 break;
1267 case QJsonValue::Array:
1268 stream << v.toArray();
1269 break;
1270 case QJsonValue::Object:
1271 stream << v.toObject();
1272 break;
1273 }
1274 return stream;
1275}
1276
1277QDataStream &operator>>(QDataStream &stream, QJsonValue &v)
1278{
1279 quint8 type;
1280 stream >> type;
1281 switch (type) {
1282 case QJsonValue::Undefined:
1283 case QJsonValue::Null:
1284 v = QJsonValue{QJsonValue::Type(type)};
1285 break;
1286 case QJsonValue::Bool: {
1287 bool b;
1288 stream >> b;
1289 v = QJsonValue(b);
1290 break;
1291 } case QJsonValue::Double: {
1292 double d;
1293 stream >> d;
1294 v = QJsonValue{d};
1295 break;
1296 } case QJsonValue::String: {
1297 QString s;
1298 stream >> s;
1299 v = QJsonValue{s};
1300 break;
1301 }
1302 case QJsonValue::Array: {
1303 QJsonArray a;
1304 stream >> a;
1305 v = QJsonValue{a};
1306 break;
1307 }
1308 case QJsonValue::Object: {
1309 QJsonObject o;
1310 stream >> o;
1311 v = QJsonValue{o};
1312 break;
1313 }
1314 default: {
1315 stream.setStatus(QDataStream::ReadCorruptData);
1316 v = QJsonValue{QJsonValue::Undefined};
1317 }
1318 }
1319 return stream;
1320}
1321#endif
1322
1323QT_END_NAMESPACE
static const QCborContainerPrivate * container(QJsonValueConstRef r) noexcept
Definition qjson_p.h:177
Combined button and popup list for selecting options.
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)