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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtbase/src/corelib/serialization/qjsonvalue.cpp