1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2020 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtCore module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include <qjsonobject.h> |
41 | #include <qjsonvalue.h> |
42 | #include <qjsonarray.h> |
43 | #include <qjsondocument.h> |
44 | #include <qurl.h> |
45 | #include <quuid.h> |
46 | #include <qvariant.h> |
47 | #include <qstringlist.h> |
48 | #include <qdebug.h> |
49 | #include "qdatastream.h" |
50 | |
51 | #include <private/qnumeric_p.h> |
52 | #include <private/qcborvalue_p.h> |
53 | |
54 | #include <qcborarray.h> |
55 | #include <qcbormap.h> |
56 | |
57 | #include "qjson_p.h" |
58 | |
59 | QT_BEGIN_NAMESPACE |
60 | |
61 | /*! |
62 | \class QJsonValue |
63 | \inmodule QtCore |
64 | \ingroup json |
65 | \ingroup shared |
66 | \reentrant |
67 | \since 5.0 |
68 | |
69 | \brief The QJsonValue class encapsulates a value in JSON. |
70 | |
71 | A value in JSON can be one of 6 basic types: |
72 | |
73 | JSON is a format to store structured data. It has 6 basic data types: |
74 | |
75 | \list |
76 | \li bool QJsonValue::Bool |
77 | \li double QJsonValue::Double |
78 | \li string QJsonValue::String |
79 | \li array QJsonValue::Array |
80 | \li object QJsonValue::Object |
81 | \li null QJsonValue::Null |
82 | \endlist |
83 | |
84 | A value can represent any of the above data types. In addition, QJsonValue has one special |
85 | flag to represent undefined values. This can be queried with isUndefined(). |
86 | |
87 | The type of the value can be queried with type() or accessors like isBool(), isString(), and so on. |
88 | Likewise, the value can be converted to the type stored in it using the toBool(), toString() and so on. |
89 | |
90 | Values are strictly typed internally and contrary to QVariant will not attempt to do any implicit type |
91 | conversions. This implies that converting to a type that is not stored in the value will return a default |
92 | constructed return value. |
93 | |
94 | \section1 QJsonValueRef |
95 | |
96 | QJsonValueRef is a helper class for QJsonArray and QJsonObject. |
97 | When you get an object of type QJsonValueRef, you can |
98 | use it as if it were a reference to a QJsonValue. If you assign to it, |
99 | the assignment will apply to the element in the QJsonArray or QJsonObject |
100 | from which you got the reference. |
101 | |
102 | The following methods return QJsonValueRef: |
103 | \list |
104 | \li \l {QJsonArray}::operator[](qsizetype i) |
105 | \li \l {QJsonObject}::operator[](const QString & key) const |
106 | \endlist |
107 | |
108 | \sa {JSON Support in Qt}, {JSON Save Game Example} |
109 | */ |
110 | |
111 | /*! |
112 | Creates a QJsonValue of type \a type. |
113 | |
114 | The default is to create a Null value. |
115 | */ |
116 | QJsonValue::QJsonValue(Type type) |
117 | { |
118 | switch (type) { |
119 | case Null: |
120 | value = QCborValue::Null; |
121 | break; |
122 | case Bool: |
123 | value = QCborValue::False; |
124 | break; |
125 | case Double: |
126 | value = QCborValue::Double; |
127 | break; |
128 | case String: |
129 | value = QCborValue::String; |
130 | break; |
131 | case Array: |
132 | value = QCborValue::Array; |
133 | break; |
134 | case Object: |
135 | value = QCborValue::Map; |
136 | break; |
137 | case Undefined: |
138 | break; |
139 | } |
140 | } |
141 | |
142 | /*! |
143 | Creates a value of type Bool, with value \a b. |
144 | */ |
145 | QJsonValue::QJsonValue(bool b) |
146 | : value(b) |
147 | { |
148 | } |
149 | |
150 | static inline QCborValue doubleValueHelper(double v) |
151 | { |
152 | qint64 n = 0; |
153 | // Convert to integer if the number is an integer and changing wouldn't |
154 | // introduce additional digit precision not present in the double. |
155 | if (convertDoubleTo<qint64>(v, &n, false /* allow_precision_upgrade */)) |
156 | return n; |
157 | else |
158 | return v; |
159 | } |
160 | |
161 | /*! |
162 | Creates a value of type Double, with value \a v. |
163 | */ |
164 | QJsonValue::QJsonValue(double v) |
165 | : value(doubleValueHelper(v)) |
166 | { |
167 | } |
168 | |
169 | /*! |
170 | \overload |
171 | Creates a value of type Double, with value \a v. |
172 | */ |
173 | QJsonValue::QJsonValue(int v) |
174 | : value(v) |
175 | { |
176 | } |
177 | |
178 | /*! |
179 | \overload |
180 | Creates a value of type Double, with value \a v. |
181 | NOTE: the integer limits for IEEE 754 double precision data is 2^53 (-9007199254740992 to +9007199254740992). |
182 | If you pass in values outside this range expect a loss of precision to occur. |
183 | */ |
184 | QJsonValue::QJsonValue(qint64 v) |
185 | : value(v) |
186 | { |
187 | } |
188 | |
189 | /*! |
190 | Creates a value of type String, with value \a s. |
191 | */ |
192 | QJsonValue::QJsonValue(const QString &s) |
193 | : value(s) |
194 | { |
195 | } |
196 | |
197 | /*! |
198 | \fn QJsonValue::QJsonValue(const char *s) |
199 | |
200 | Creates a value of type String with value \a s, assuming |
201 | UTF-8 encoding of the input. |
202 | |
203 | You can disable this constructor by defining \c |
204 | QT_NO_CAST_FROM_ASCII when you compile your applications. |
205 | |
206 | \since 5.3 |
207 | */ |
208 | |
209 | /*! |
210 | Creates a value of type String, with value \a s. |
211 | */ |
212 | QJsonValue::QJsonValue(QLatin1String s) |
213 | : value(s) |
214 | { |
215 | } |
216 | |
217 | /*! |
218 | Creates a value of type Array, with value \a a. |
219 | */ |
220 | QJsonValue::QJsonValue(const QJsonArray &a) |
221 | : value(QCborArray::fromJsonArray(a)) |
222 | { |
223 | } |
224 | |
225 | /*! |
226 | Creates a value of type Object, with value \a o. |
227 | */ |
228 | QJsonValue::QJsonValue(const QJsonObject &o) |
229 | : value(QCborMap::fromJsonObject(o)) |
230 | { |
231 | } |
232 | |
233 | |
234 | /*! |
235 | Destroys the value. |
236 | */ |
237 | QJsonValue::~QJsonValue() = default; |
238 | |
239 | /*! |
240 | Creates a copy of \a other. |
241 | */ |
242 | QJsonValue::QJsonValue(const QJsonValue &other) |
243 | : value(other.value) |
244 | { |
245 | } |
246 | |
247 | /*! |
248 | Assigns the value stored in \a other to this object. |
249 | */ |
250 | QJsonValue &QJsonValue::operator =(const QJsonValue &other) |
251 | { |
252 | QJsonValue copy(other); |
253 | swap(copy); |
254 | return *this; |
255 | } |
256 | |
257 | QJsonValue::QJsonValue(QJsonValue &&other) noexcept |
258 | : value(std::move(other.value)) |
259 | { |
260 | other.value = QCborValue(nullptr); |
261 | } |
262 | |
263 | void QJsonValue::swap(QJsonValue &other) noexcept |
264 | { |
265 | value.swap(other.value); |
266 | } |
267 | |
268 | /*! |
269 | \fn QJsonValue::QJsonValue(QJsonValue &&other) |
270 | \since 5.10 |
271 | |
272 | Move-constructs a QJsonValue from \a other. |
273 | */ |
274 | |
275 | /*! |
276 | \fn QJsonValue &QJsonValue::operator =(QJsonValue &&other) |
277 | \since 5.10 |
278 | |
279 | Move-assigns \a other to this value. |
280 | */ |
281 | |
282 | /*! |
283 | \fn void QJsonValue::swap(QJsonValue &other) |
284 | \since 5.10 |
285 | |
286 | Swaps the value \a other with this. This operation is very fast and never fails. |
287 | */ |
288 | |
289 | /*! |
290 | \fn bool QJsonValue::isNull() const |
291 | |
292 | Returns \c true if the value is null. |
293 | */ |
294 | |
295 | /*! |
296 | \fn bool QJsonValue::isBool() const |
297 | |
298 | Returns \c true if the value contains a boolean. |
299 | |
300 | \sa toBool() |
301 | */ |
302 | |
303 | /*! |
304 | \fn bool QJsonValue::isDouble() const |
305 | |
306 | Returns \c true if the value contains a double. |
307 | |
308 | \sa toDouble() |
309 | */ |
310 | |
311 | /*! |
312 | \fn bool QJsonValue::isString() const |
313 | |
314 | Returns \c true if the value contains a string. |
315 | |
316 | \sa toString() |
317 | */ |
318 | |
319 | /*! |
320 | \fn bool QJsonValue::isArray() const |
321 | |
322 | Returns \c true if the value contains an array. |
323 | |
324 | \sa toArray() |
325 | */ |
326 | |
327 | /*! |
328 | \fn bool QJsonValue::isObject() const |
329 | |
330 | Returns \c true if the value contains an object. |
331 | |
332 | \sa toObject() |
333 | */ |
334 | |
335 | /*! |
336 | \fn bool QJsonValue::isUndefined() const |
337 | |
338 | Returns \c true if the value is undefined. This can happen in certain |
339 | error cases as e.g. accessing a non existing key in a QJsonObject. |
340 | */ |
341 | |
342 | /*! |
343 | Converts \a variant to a QJsonValue and returns it. |
344 | |
345 | The conversion will convert QVariant types as follows: |
346 | |
347 | \table |
348 | \header |
349 | \li Source type |
350 | \li Destination type |
351 | \row |
352 | \li |
353 | \list |
354 | \li QMetaType::Nullptr |
355 | \endlist |
356 | \li QJsonValue::Null |
357 | \row |
358 | \li |
359 | \list |
360 | \li QMetaType::Bool |
361 | \endlist |
362 | \li QJsonValue::Bool |
363 | \row |
364 | \li |
365 | \list |
366 | \li QMetaType::Int |
367 | \li QMetaType::UInt |
368 | \li QMetaType::LongLong |
369 | \li QMetaType::ULongLong |
370 | \li QMetaType::Float |
371 | \li QMetaType::Double |
372 | \endlist |
373 | \li QJsonValue::Double |
374 | \row |
375 | \li |
376 | \list |
377 | \li QMetaType::QString |
378 | \endlist |
379 | \li QJsonValue::String |
380 | \row |
381 | \li |
382 | \list |
383 | \li QMetaType::QStringList |
384 | \li QMetaType::QVariantList |
385 | \endlist |
386 | \li QJsonValue::Array |
387 | \row |
388 | \li |
389 | \list |
390 | \li QMetaType::QVariantMap |
391 | \li QMetaType::QVariantHash |
392 | \endlist |
393 | \li QJsonValue::Object |
394 | |
395 | \row |
396 | \li |
397 | \list |
398 | \li QMetaType::QUrl |
399 | \endlist |
400 | \li QJsonValue::String. The conversion will use QUrl::toString() with flag |
401 | QUrl::FullyEncoded, so as to ensure maximum compatibility in parsing the URL |
402 | \row |
403 | \li |
404 | \list |
405 | \li QMetaType::QUuid |
406 | \endlist |
407 | \li QJsonValue::String. Since Qt 5.11, the resulting string will not include braces |
408 | \row |
409 | \li |
410 | \list |
411 | \li QMetaType::QCborValue |
412 | \endlist |
413 | \li Whichever type QCborValue::toJsonValue() returns. |
414 | \row |
415 | \li |
416 | \list |
417 | \li QMetaType::QCborArray |
418 | \endlist |
419 | \li QJsonValue::Array. See QCborValue::toJsonValue() for conversion restrictions. |
420 | \row |
421 | \li |
422 | \list |
423 | \li QMetaType::QCborMap |
424 | \endlist |
425 | \li QJsonValue::Map. See QCborValue::toJsonValue() for conversion restrictions and the |
426 | "stringification" of map keys. |
427 | \endtable |
428 | |
429 | \section2 Loss of information and other types |
430 | |
431 | QVariant can carry more information than is representable in JSON. If the |
432 | QVariant is not one of the types above, the conversion is not guaranteed |
433 | and is subject to change in future versions of Qt, as the UUID one did. |
434 | Code should strive not to use any other types than those listed above. |
435 | |
436 | If QVariant::isNull() returns true, a null QJsonValue is returned or |
437 | inserted into the list or object, regardless of the type carried by |
438 | QVariant. Note the behavior change in Qt 6.0 affecting QVariant::isNull() |
439 | also affects this function. |
440 | |
441 | A floating point value that is either an infinity or NaN will be converted |
442 | to a null JSON value. Since Qt 6.0, QJsonValue can store the full precision |
443 | of any 64-bit signed integer without loss, but in previous versions values |
444 | outside the range of ±2^53 may lose precision. Unsigned 64-bit values |
445 | greater than or equal to 2^63 will either lose precision or alias to |
446 | negative values, so QMetaType::ULongLong should be avoided. |
447 | |
448 | For other types not listed above, a conversion to string will be attempted, |
449 | usually but not always by calling QVariant::toString(). If the conversion |
450 | fails the value is replaced by a null JSON value. Note that |
451 | QVariant::toString() is also lossy for the majority of types. For example, |
452 | if the passed QVariant is representing raw byte array data, it is recommended |
453 | to pre-encode it to \l {https://www.ietf.org/rfc/rfc4648.txt}{Base64} (or |
454 | another lossless encoding), otherwise a lossy conversion using QString::fromUtf8() |
455 | will be used. |
456 | |
457 | Please note that the conversions via QVariant::toString() are subject to |
458 | change at any time. Both QVariant and QJsonValue may be extended in the |
459 | future to support more types, which will result in a change in how this |
460 | function performs conversions. |
461 | |
462 | \sa toVariant(), QCborValue::fromVariant() |
463 | */ |
464 | QJsonValue QJsonValue::fromVariant(const QVariant &variant) |
465 | { |
466 | switch (variant.metaType().id()) { |
467 | case QMetaType::Nullptr: |
468 | return QJsonValue(Null); |
469 | case QMetaType::Bool: |
470 | return QJsonValue(variant.toBool()); |
471 | case QMetaType::Short: |
472 | case QMetaType::UShort: |
473 | case QMetaType::Int: |
474 | case QMetaType::UInt: |
475 | case QMetaType::LongLong: |
476 | return QJsonValue(variant.toLongLong()); |
477 | case QMetaType::ULongLong: |
478 | if (variant.toULongLong() <= static_cast<uint64_t>(std::numeric_limits<qint64>::max())) |
479 | return QJsonValue(variant.toLongLong()); |
480 | Q_FALLTHROUGH(); |
481 | case QMetaType::Float: |
482 | case QMetaType::Double: { |
483 | double v = variant.toDouble(); |
484 | return qt_is_finite(v) ? QJsonValue(v) : QJsonValue(); |
485 | } |
486 | case QMetaType::QString: |
487 | return QJsonValue(variant.toString()); |
488 | case QMetaType::QStringList: |
489 | return QJsonValue(QJsonArray::fromStringList(variant.toStringList())); |
490 | case QMetaType::QVariantList: |
491 | return QJsonValue(QJsonArray::fromVariantList(variant.toList())); |
492 | case QMetaType::QVariantMap: |
493 | return QJsonValue(QJsonObject::fromVariantMap(variant.toMap())); |
494 | case QMetaType::QVariantHash: |
495 | return QJsonValue(QJsonObject::fromVariantHash(variant.toHash())); |
496 | #ifndef QT_BOOTSTRAPPED |
497 | case QMetaType::QUrl: |
498 | return QJsonValue(variant.toUrl().toString(QUrl::FullyEncoded)); |
499 | case QMetaType::QUuid: |
500 | return variant.toUuid().toString(QUuid::WithoutBraces); |
501 | case QMetaType::QJsonValue: |
502 | return variant.toJsonValue(); |
503 | case QMetaType::QJsonObject: |
504 | return variant.toJsonObject(); |
505 | case QMetaType::QJsonArray: |
506 | return variant.toJsonArray(); |
507 | case QMetaType::QJsonDocument: { |
508 | QJsonDocument doc = variant.toJsonDocument(); |
509 | return doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object()); |
510 | } |
511 | case QMetaType::QCborValue: |
512 | return qvariant_cast<QCborValue>(variant).toJsonValue(); |
513 | case QMetaType::QCborArray: |
514 | return qvariant_cast<QCborArray>(variant).toJsonArray(); |
515 | case QMetaType::QCborMap: |
516 | return qvariant_cast<QCborMap>(variant).toJsonObject(); |
517 | #endif |
518 | default: |
519 | break; |
520 | } |
521 | QString string = variant.toString(); |
522 | if (string.isEmpty()) |
523 | return QJsonValue(); |
524 | return QJsonValue(string); |
525 | } |
526 | |
527 | /*! |
528 | Converts the value to a \l {QVariant::}{QVariant()}. |
529 | |
530 | The QJsonValue types will be converted as follows: |
531 | |
532 | \value Null QMetaType::Nullptr |
533 | \value Bool QMetaType::Bool |
534 | \value Double QMetaType::Double or QMetaType::LongLong |
535 | \value String QString |
536 | \value Array QVariantList |
537 | \value Object QVariantMap |
538 | \value Undefined \l {QVariant::}{QVariant()} |
539 | |
540 | \sa fromVariant() |
541 | */ |
542 | QVariant QJsonValue::toVariant() const |
543 | { |
544 | switch (value.type()) { |
545 | case QCborValue::True: |
546 | return true; |
547 | case QCborValue::False: |
548 | return false; |
549 | case QCborValue::Integer: |
550 | return toInteger(); |
551 | case QCborValue::Double: |
552 | return toDouble(); |
553 | case QCborValue::String: |
554 | return toString(); |
555 | case QCborValue::Array: |
556 | return toArray().toVariantList(); |
557 | case QCborValue::Map: |
558 | return toObject().toVariantMap(); |
559 | case QCborValue::Null: |
560 | return QVariant::fromValue(nullptr); |
561 | case QCborValue::Undefined: |
562 | default: |
563 | break; |
564 | } |
565 | return QVariant(); |
566 | } |
567 | |
568 | /*! |
569 | \enum QJsonValue::Type |
570 | |
571 | This enum describes the type of the JSON value. |
572 | |
573 | \value Null A Null value |
574 | \value Bool A boolean value. Use toBool() to convert to a bool. |
575 | \value Double A number value. Use toDouble() to convert to a double, |
576 | or toInteger() to convert to a qint64. |
577 | \value String A string. Use toString() to convert to a QString. |
578 | \value Array An array. Use toArray() to convert to a QJsonArray. |
579 | \value Object An object. Use toObject() to convert to a QJsonObject. |
580 | \value Undefined The value is undefined. This is usually returned as an |
581 | error condition, when trying to read an out of bounds value |
582 | in an array or a non existent key in an object. |
583 | */ |
584 | |
585 | /*! |
586 | Returns the type of the value. |
587 | |
588 | \sa QJsonValue::Type |
589 | */ |
590 | QJsonValue::Type QJsonValue::type() const |
591 | { |
592 | switch (value.type()) { |
593 | case QCborValue::Null: |
594 | return QJsonValue::Null; |
595 | case QCborValue::True: |
596 | case QCborValue::False: |
597 | return QJsonValue::Bool; |
598 | case QCborValue::Double: |
599 | case QCborValue::Integer: |
600 | return QJsonValue::Double; |
601 | case QCborValue::String: |
602 | return QJsonValue::String; |
603 | case QCborValue::Array: |
604 | return QJsonValue::Array; |
605 | case QCborValue::Map: |
606 | return QJsonValue::Object; |
607 | case QCborValue::Undefined: |
608 | default: |
609 | return QJsonValue::Undefined; |
610 | } |
611 | } |
612 | |
613 | /*! |
614 | Converts the value to a bool and returns it. |
615 | |
616 | If type() is not bool, the \a defaultValue will be returned. |
617 | */ |
618 | bool QJsonValue::toBool(bool defaultValue) const |
619 | { |
620 | switch (value.type()) { |
621 | case QCborValue::True: |
622 | return true; |
623 | case QCborValue::False: |
624 | return false; |
625 | default: |
626 | return defaultValue; |
627 | } |
628 | } |
629 | |
630 | /*! |
631 | \since 5.2 |
632 | Converts the value to an int and returns it. |
633 | |
634 | If type() is not Double or the value is not a whole number, |
635 | the \a defaultValue will be returned. |
636 | */ |
637 | int QJsonValue::toInt(int defaultValue) const |
638 | { |
639 | switch (value.type()) { |
640 | case QCborValue::Double: { |
641 | int dblInt; |
642 | if (convertDoubleTo<int>(toDouble(), &dblInt)) |
643 | return dblInt; |
644 | break; |
645 | } |
646 | case QCborValue::Integer: { |
647 | const auto n = value.toInteger(); |
648 | if (qint64(int(n)) == n) |
649 | return int(n); |
650 | break; |
651 | } |
652 | default: |
653 | break; |
654 | } |
655 | return defaultValue; |
656 | } |
657 | |
658 | /*! |
659 | \since 6.0 |
660 | Converts the value to an integer and returns it. |
661 | |
662 | If type() is not Double or the value is not a whole number |
663 | representable as qint64, the \a defaultValue will be returned. |
664 | */ |
665 | qint64 QJsonValue::toInteger(qint64 defaultValue) const |
666 | { |
667 | switch (value.type()) { |
668 | case QCborValue::Integer: |
669 | return value.toInteger(); |
670 | case QCborValue::Double: { |
671 | qint64 dblInt; |
672 | if (convertDoubleTo<qint64>(toDouble(), &dblInt)) |
673 | return dblInt; |
674 | break; |
675 | } |
676 | default: |
677 | break; |
678 | } |
679 | return defaultValue; |
680 | } |
681 | |
682 | /*! |
683 | Converts the value to a double and returns it. |
684 | |
685 | If type() is not Double, the \a defaultValue will be returned. |
686 | */ |
687 | double QJsonValue::toDouble(double defaultValue) const |
688 | { |
689 | return value.toDouble(defaultValue); |
690 | } |
691 | |
692 | /*! |
693 | Converts the value to a QString and returns it. |
694 | |
695 | If type() is not String, the \a defaultValue will be returned. |
696 | */ |
697 | QString QJsonValue::toString(const QString &defaultValue) const |
698 | { |
699 | return value.toString(defaultValue); |
700 | } |
701 | |
702 | /*! |
703 | Converts the value to a QString and returns it. |
704 | |
705 | If type() is not String, a null QString will be returned. |
706 | |
707 | \sa QString::isNull() |
708 | */ |
709 | QString QJsonValue::toString() const |
710 | { |
711 | return value.toString(); |
712 | } |
713 | |
714 | /*! |
715 | Converts the value to an array and returns it. |
716 | |
717 | If type() is not Array, the \a defaultValue will be returned. |
718 | */ |
719 | QJsonArray QJsonValue::toArray(const QJsonArray &defaultValue) const |
720 | { |
721 | const auto dd = QJsonPrivate::Value::container(value); |
722 | const auto n = QJsonPrivate::Value::valueHelper(value); |
723 | if (value.type() != QCborValue::Array || n >= 0 || !dd) |
724 | return defaultValue; |
725 | |
726 | return QJsonArray(dd); |
727 | } |
728 | |
729 | /*! |
730 | \overload |
731 | |
732 | Converts the value to an array and returns it. |
733 | |
734 | If type() is not Array, a \l{QJsonArray::}{QJsonArray()} will be returned. |
735 | */ |
736 | QJsonArray QJsonValue::toArray() const |
737 | { |
738 | return toArray(QJsonArray()); |
739 | } |
740 | |
741 | /*! |
742 | Converts the value to an object and returns it. |
743 | |
744 | If type() is not Object, the \a defaultValue will be returned. |
745 | */ |
746 | QJsonObject QJsonValue::toObject(const QJsonObject &defaultValue) const |
747 | { |
748 | const auto dd = QJsonPrivate::Value::container(value); |
749 | const auto n = QJsonPrivate::Value::valueHelper(value); |
750 | if (value.type() != QCborValue::Map || n >= 0 || !dd) |
751 | return defaultValue; |
752 | |
753 | return QJsonObject(dd); |
754 | } |
755 | |
756 | /*! |
757 | \overload |
758 | |
759 | Converts the value to an object and returns it. |
760 | |
761 | If type() is not Object, the \l {QJsonObject::}{QJsonObject()} will be returned. |
762 | */ |
763 | QJsonObject QJsonValue::toObject() const |
764 | { |
765 | return toObject(QJsonObject()); |
766 | } |
767 | |
768 | #if QT_STRINGVIEW_LEVEL < 2 |
769 | /*! |
770 | Returns a QJsonValue representing the value for the key \a key. |
771 | |
772 | Equivalent to calling toObject().value(key). |
773 | |
774 | The returned QJsonValue is QJsonValue::Undefined if the key does not exist, |
775 | or if isObject() is false. |
776 | |
777 | \since 5.10 |
778 | |
779 | \sa QJsonValue, QJsonValue::isUndefined(), QJsonObject |
780 | */ |
781 | const QJsonValue QJsonValue::operator[](const QString &key) const |
782 | { |
783 | return (*this)[QStringView(key)]; |
784 | } |
785 | #endif |
786 | |
787 | /*! |
788 | \overload |
789 | \since 5.14 |
790 | */ |
791 | const QJsonValue QJsonValue::operator[](QStringView key) const |
792 | { |
793 | if (!isObject()) |
794 | return QJsonValue(QJsonValue::Undefined); |
795 | |
796 | return toObject().value(key); |
797 | } |
798 | |
799 | /*! |
800 | \overload |
801 | \since 5.10 |
802 | */ |
803 | const QJsonValue QJsonValue::operator[](QLatin1String key) const |
804 | { |
805 | if (!isObject()) |
806 | return QJsonValue(QJsonValue::Undefined); |
807 | |
808 | return toObject().value(key); |
809 | } |
810 | |
811 | /*! |
812 | Returns a QJsonValue representing the value for index \a i. |
813 | |
814 | Equivalent to calling toArray().at(i). |
815 | |
816 | The returned QJsonValue is QJsonValue::Undefined, if \a i is out of bounds, |
817 | or if isArray() is false. |
818 | |
819 | \since 5.10 |
820 | |
821 | \sa QJsonValue, QJsonValue::isUndefined(), QJsonArray |
822 | */ |
823 | const QJsonValue QJsonValue::operator[](qsizetype i) const |
824 | { |
825 | if (!isArray()) |
826 | return QJsonValue(QJsonValue::Undefined); |
827 | |
828 | return toArray().at(i); |
829 | } |
830 | |
831 | /*! |
832 | Returns \c true if the value is equal to \a other. |
833 | */ |
834 | bool QJsonValue::operator==(const QJsonValue &other) const |
835 | { |
836 | if (value.type() != other.value.type()) { |
837 | if (isDouble() && other.isDouble()) { |
838 | // One value Cbor integer, one Cbor double, should interact as doubles. |
839 | return toDouble() == other.toDouble(); |
840 | } |
841 | return false; |
842 | } |
843 | |
844 | switch (value.type()) { |
845 | case QCborValue::Undefined: |
846 | case QCborValue::Null: |
847 | case QCborValue::True: |
848 | case QCborValue::False: |
849 | break; |
850 | case QCborValue::Double: |
851 | return toDouble() == other.toDouble(); |
852 | case QCborValue::Integer: |
853 | return QJsonPrivate::Value::valueHelper(value) |
854 | == QJsonPrivate::Value::valueHelper(other.value); |
855 | case QCborValue::String: |
856 | return toString() == other.toString(); |
857 | case QCborValue::Array: |
858 | return toArray() == other.toArray(); |
859 | case QCborValue::Map: |
860 | return toObject() == other.toObject(); |
861 | default: |
862 | return false; |
863 | } |
864 | return true; |
865 | } |
866 | |
867 | /*! |
868 | Returns \c true if the value is not equal to \a other. |
869 | */ |
870 | bool QJsonValue::operator!=(const QJsonValue &other) const |
871 | { |
872 | return !(*this == other); |
873 | } |
874 | |
875 | /*! |
876 | \class QJsonValueRef |
877 | \inmodule QtCore |
878 | \reentrant |
879 | \brief The QJsonValueRef class is a helper class for QJsonValue. |
880 | |
881 | \internal |
882 | |
883 | \ingroup json |
884 | |
885 | When you get an object of type QJsonValueRef, if you can assign to it, |
886 | the assignment will apply to the character in the string from |
887 | which you got the reference. That is its whole purpose in life. |
888 | |
889 | You can use it exactly in the same way as a reference to a QJsonValue. |
890 | |
891 | The QJsonValueRef becomes invalid once modifications are made to the |
892 | string: if you want to keep the character, copy it into a QJsonValue. |
893 | |
894 | Most of the QJsonValue member functions also exist in QJsonValueRef. |
895 | However, they are not explicitly documented here. |
896 | */ |
897 | |
898 | |
899 | QJsonValueRef &QJsonValueRef::operator =(const QJsonValue &val) |
900 | { |
901 | if (is_object) |
902 | o->setValueAt(index, val); |
903 | else |
904 | a->replace(index, val); |
905 | |
906 | return *this; |
907 | } |
908 | |
909 | QJsonValueRef &QJsonValueRef::operator =(const QJsonValueRef &ref) |
910 | { |
911 | if (is_object) |
912 | o->setValueAt(index, ref); |
913 | else |
914 | a->replace(index, ref); |
915 | |
916 | return *this; |
917 | } |
918 | |
919 | QVariant QJsonValueRef::toVariant() const |
920 | { |
921 | return toValue().toVariant(); |
922 | } |
923 | |
924 | QJsonArray QJsonValueRef::toArray() const |
925 | { |
926 | return toValue().toArray(); |
927 | } |
928 | |
929 | QJsonObject QJsonValueRef::toObject() const |
930 | { |
931 | return toValue().toObject(); |
932 | } |
933 | |
934 | QJsonValue QJsonValueRef::toValue() const |
935 | { |
936 | if (!is_object) |
937 | return a->at(index); |
938 | return o->valueAt(index); |
939 | } |
940 | |
941 | size_t qHash(const QJsonValue &value, size_t seed) |
942 | { |
943 | switch (value.type()) { |
944 | case QJsonValue::Null: |
945 | return qHash(nullptr, seed); |
946 | case QJsonValue::Bool: |
947 | return qHash(value.toBool(), seed); |
948 | case QJsonValue::Double: |
949 | return qHash(value.toDouble(), seed); |
950 | case QJsonValue::String: |
951 | return qHash(value.toString(), seed); |
952 | case QJsonValue::Array: |
953 | return qHash(value.toArray(), seed); |
954 | case QJsonValue::Object: |
955 | return qHash(value.toObject(), seed); |
956 | case QJsonValue::Undefined: |
957 | return seed; |
958 | } |
959 | Q_UNREACHABLE(); |
960 | return 0; |
961 | } |
962 | |
963 | #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) |
964 | QDebug operator<<(QDebug dbg, const QJsonValue &o) |
965 | { |
966 | QDebugStateSaver saver(dbg); |
967 | switch (o.value.type()) { |
968 | case QCborValue::Undefined: |
969 | dbg << "QJsonValue(undefined)" ; |
970 | break; |
971 | case QCborValue::Null: |
972 | dbg << "QJsonValue(null)" ; |
973 | break; |
974 | case QCborValue::True: |
975 | case QCborValue::False: |
976 | dbg.nospace() << "QJsonValue(bool, " << o.toBool() << ')'; |
977 | break; |
978 | case QCborValue::Integer: |
979 | dbg.nospace() << "QJsonValue(double, " << o.toInteger() << ')'; |
980 | break; |
981 | case QCborValue::Double: |
982 | dbg.nospace() << "QJsonValue(double, " << o.toDouble() << ')'; |
983 | break; |
984 | case QCborValue::String: |
985 | dbg.nospace() << "QJsonValue(string, " << o.toString() << ')'; |
986 | break; |
987 | case QCborValue::Array: |
988 | dbg.nospace() << "QJsonValue(array, " ; |
989 | dbg << o.toArray(); |
990 | dbg << ')'; |
991 | break; |
992 | case QCborValue::Map: |
993 | dbg.nospace() << "QJsonValue(object, " ; |
994 | dbg << o.toObject(); |
995 | dbg << ')'; |
996 | break; |
997 | default: |
998 | Q_UNREACHABLE(); |
999 | } |
1000 | return dbg; |
1001 | } |
1002 | #endif |
1003 | |
1004 | #ifndef QT_NO_DATASTREAM |
1005 | QDataStream &operator<<(QDataStream &stream, const QJsonValue &v) |
1006 | { |
1007 | quint8 type = v.type(); |
1008 | stream << type; |
1009 | switch (type) { |
1010 | case QJsonValue::Undefined: |
1011 | case QJsonValue::Null: |
1012 | break; |
1013 | case QJsonValue::Bool: |
1014 | stream << v.toBool(); |
1015 | break; |
1016 | case QJsonValue::Double: |
1017 | stream << v.toDouble(); |
1018 | break; |
1019 | case QJsonValue::String: |
1020 | stream << v.toString(); |
1021 | break; |
1022 | case QJsonValue::Array: |
1023 | stream << v.toArray(); |
1024 | break; |
1025 | case QJsonValue::Object: |
1026 | stream << v.toObject(); |
1027 | break; |
1028 | } |
1029 | return stream; |
1030 | } |
1031 | |
1032 | QDataStream &operator>>(QDataStream &stream, QJsonValue &v) |
1033 | { |
1034 | quint8 type; |
1035 | stream >> type; |
1036 | switch (type) { |
1037 | case QJsonValue::Undefined: |
1038 | case QJsonValue::Null: |
1039 | v = QJsonValue{QJsonValue::Type(type)}; |
1040 | break; |
1041 | case QJsonValue::Bool: { |
1042 | bool b; |
1043 | stream >> b; |
1044 | v = QJsonValue(b); |
1045 | break; |
1046 | } case QJsonValue::Double: { |
1047 | double d; |
1048 | stream >> d; |
1049 | v = QJsonValue{d}; |
1050 | break; |
1051 | } case QJsonValue::String: { |
1052 | QString s; |
1053 | stream >> s; |
1054 | v = QJsonValue{s}; |
1055 | break; |
1056 | } |
1057 | case QJsonValue::Array: { |
1058 | QJsonArray a; |
1059 | stream >> a; |
1060 | v = QJsonValue{a}; |
1061 | break; |
1062 | } |
1063 | case QJsonValue::Object: { |
1064 | QJsonObject o; |
1065 | stream >> o; |
1066 | v = QJsonValue{o}; |
1067 | break; |
1068 | } |
1069 | default: { |
1070 | stream.setStatus(QDataStream::ReadCorruptData); |
1071 | v = QJsonValue{QJsonValue::Undefined}; |
1072 | } |
1073 | } |
1074 | return stream; |
1075 | } |
1076 | #endif |
1077 | |
1078 | QT_END_NAMESPACE |
1079 | |