1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 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[](int 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 | : d(nullptr), t(QCborValue::Undefined) |
118 | { |
119 | switch (type) { |
120 | case Null: |
121 | t = QCborValue::Null; |
122 | break; |
123 | case Bool: |
124 | t = QCborValue::False; |
125 | break; |
126 | case Double: |
127 | t = QCborValue::Double; |
128 | break; |
129 | case String: |
130 | t = QCborValue::String; |
131 | break; |
132 | case Array: |
133 | t = QCborValue::Array; |
134 | break; |
135 | case Object: |
136 | t = QCborValue::Map; |
137 | break; |
138 | case Undefined: |
139 | break; |
140 | } |
141 | } |
142 | |
143 | /*! |
144 | Creates a value of type Bool, with value \a b. |
145 | */ |
146 | QJsonValue::QJsonValue(bool b) |
147 | : t(b ? QCborValue::True : QCborValue::False) |
148 | { |
149 | } |
150 | |
151 | /*! |
152 | Creates a value of type Double, with value \a v. |
153 | */ |
154 | QJsonValue::QJsonValue(double v) |
155 | : d(nullptr) |
156 | { |
157 | if (convertDoubleTo(v, value: &n)) { |
158 | t = QCborValue::Integer; |
159 | } else { |
160 | memcpy(dest: &n, src: &v, n: sizeof(n)); |
161 | t = QCborValue::Double; |
162 | } |
163 | } |
164 | |
165 | /*! |
166 | \overload |
167 | Creates a value of type Double, with value \a v. |
168 | */ |
169 | QJsonValue::QJsonValue(int v) |
170 | : n(v), t(QCborValue::Integer) |
171 | { |
172 | } |
173 | |
174 | /*! |
175 | \overload |
176 | Creates a value of type Double, with value \a v. |
177 | NOTE: the integer limits for IEEE 754 double precision data is 2^53 (-9007199254740992 to +9007199254740992). |
178 | If you pass in values outside this range expect a loss of precision to occur. |
179 | */ |
180 | QJsonValue::QJsonValue(qint64 v) |
181 | : n(v), t(QCborValue::Integer) |
182 | { |
183 | } |
184 | |
185 | /*! |
186 | Creates a value of type String, with value \a s. |
187 | */ |
188 | QJsonValue::QJsonValue(const QString &s) |
189 | : QJsonValue(QJsonPrivate::Value::fromTrustedCbor(v: s)) |
190 | { |
191 | } |
192 | |
193 | /*! |
194 | \fn QJsonValue::QJsonValue(const char *s) |
195 | |
196 | Creates a value of type String with value \a s, assuming |
197 | UTF-8 encoding of the input. |
198 | |
199 | You can disable this constructor by defining \c |
200 | QT_NO_CAST_FROM_ASCII when you compile your applications. |
201 | |
202 | \since 5.3 |
203 | */ |
204 | |
205 | // ### Qt6: remove |
206 | void QJsonValue::stringDataFromQStringHelper(const QString &string) |
207 | { |
208 | *this = QJsonValue(string); |
209 | } |
210 | |
211 | /*! |
212 | Creates a value of type String, with value \a s. |
213 | */ |
214 | QJsonValue::QJsonValue(QLatin1String s) |
215 | : QJsonValue(QJsonPrivate::Value::fromTrustedCbor(v: s)) |
216 | { |
217 | } |
218 | |
219 | /*! |
220 | Creates a value of type Array, with value \a a. |
221 | */ |
222 | QJsonValue::QJsonValue(const QJsonArray &a) |
223 | : n(-1), d(a.a), t(QCborValue::Array) |
224 | { |
225 | } |
226 | |
227 | /*! |
228 | Creates a value of type Object, with value \a o. |
229 | */ |
230 | QJsonValue::QJsonValue(const QJsonObject &o) |
231 | : n(-1), d(o.o), t(QCborValue::Map) |
232 | { |
233 | } |
234 | |
235 | |
236 | /*! |
237 | Destroys the value. |
238 | */ |
239 | QJsonValue::~QJsonValue() = default; |
240 | |
241 | /*! |
242 | Creates a copy of \a other. |
243 | */ |
244 | QJsonValue::QJsonValue(const QJsonValue &other) |
245 | { |
246 | n = other.n; |
247 | t = other.t; |
248 | d = other.d; |
249 | } |
250 | |
251 | /*! |
252 | Assigns the value stored in \a other to this object. |
253 | */ |
254 | QJsonValue &QJsonValue::operator =(const QJsonValue &other) |
255 | { |
256 | QJsonValue copy(other); |
257 | swap(other&: copy); |
258 | return *this; |
259 | } |
260 | |
261 | QJsonValue::QJsonValue(QJsonValue &&other) noexcept : |
262 | n(other.n), |
263 | d(other.d), |
264 | t(other.t) |
265 | { |
266 | other.n = 0; |
267 | other.d = nullptr; |
268 | other.t = QCborValue::Null; |
269 | } |
270 | |
271 | void QJsonValue::swap(QJsonValue &other) noexcept |
272 | { |
273 | qSwap(value1&: n, value2&: other.n); |
274 | qSwap(value1&: d, value2&: other.d); |
275 | qSwap(value1&: t, value2&: other.t); |
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 | |
296 | Swaps the value \a other with this. This operation is very fast and never fails. |
297 | */ |
298 | |
299 | /*! |
300 | \fn bool QJsonValue::isNull() const |
301 | |
302 | Returns \c true if the value is null. |
303 | */ |
304 | |
305 | /*! |
306 | \fn bool QJsonValue::isBool() const |
307 | |
308 | Returns \c true if the value contains a boolean. |
309 | |
310 | \sa toBool() |
311 | */ |
312 | |
313 | /*! |
314 | \fn bool QJsonValue::isDouble() const |
315 | |
316 | Returns \c true if the value contains a double. |
317 | |
318 | \sa toDouble() |
319 | */ |
320 | |
321 | /*! |
322 | \fn bool QJsonValue::isString() const |
323 | |
324 | Returns \c true if the value contains a string. |
325 | |
326 | \sa toString() |
327 | */ |
328 | |
329 | /*! |
330 | \fn bool QJsonValue::isArray() const |
331 | |
332 | Returns \c true if the value contains an array. |
333 | |
334 | \sa toArray() |
335 | */ |
336 | |
337 | /*! |
338 | \fn bool QJsonValue::isObject() const |
339 | |
340 | Returns \c true if the value contains an object. |
341 | |
342 | \sa toObject() |
343 | */ |
344 | |
345 | /*! |
346 | \fn bool QJsonValue::isUndefined() const |
347 | |
348 | Returns \c true if the value is undefined. This can happen in certain |
349 | error cases as e.g. accessing a non existing key in a QJsonObject. |
350 | */ |
351 | |
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. The values outside the range of ±2^53 may lose precision, |
453 | because they are converted to a double QJsonValue. |
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 {https://www.ietf.org/rfc/rfc4648.txt}{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 | */ |
471 | QJsonValue QJsonValue::fromVariant(const QVariant &variant) |
472 | { |
473 | switch (variant.userType()) { |
474 | case QMetaType::Nullptr: |
475 | return QJsonValue(Null); |
476 | case QMetaType::Bool: |
477 | return QJsonValue(variant.toBool()); |
478 | case QMetaType::Int: |
479 | case QMetaType::Float: |
480 | case QMetaType::Double: |
481 | case QMetaType::LongLong: |
482 | case QMetaType::ULongLong: |
483 | case QMetaType::UInt: { |
484 | double v = variant.toDouble(); |
485 | return qt_is_finite(d: v) ? QJsonValue(v) : QJsonValue(); |
486 | } |
487 | case QMetaType::QString: |
488 | return QJsonValue(variant.toString()); |
489 | case QMetaType::QStringList: |
490 | return QJsonValue(QJsonArray::fromStringList(list: variant.toStringList())); |
491 | case QMetaType::QVariantList: |
492 | return QJsonValue(QJsonArray::fromVariantList(list: variant.toList())); |
493 | case QMetaType::QVariantMap: |
494 | return QJsonValue(QJsonObject::fromVariantMap(map: variant.toMap())); |
495 | case QMetaType::QVariantHash: |
496 | return QJsonValue(QJsonObject::fromVariantHash(map: variant.toHash())); |
497 | #ifndef QT_BOOTSTRAPPED |
498 | case QMetaType::QUrl: |
499 | return QJsonValue(variant.toUrl().toString(options: QUrl::FullyEncoded)); |
500 | case QMetaType::QUuid: |
501 | return variant.toUuid().toString(mode: QUuid::WithoutBraces); |
502 | case QMetaType::QJsonValue: |
503 | return variant.toJsonValue(); |
504 | case QMetaType::QJsonObject: |
505 | return variant.toJsonObject(); |
506 | case QMetaType::QJsonArray: |
507 | return variant.toJsonArray(); |
508 | case QMetaType::QJsonDocument: { |
509 | QJsonDocument doc = variant.toJsonDocument(); |
510 | return doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object()); |
511 | } |
512 | case QMetaType::QCborValue: |
513 | return qvariant_cast<QCborValue>(v: variant).toJsonValue(); |
514 | case QMetaType::QCborArray: |
515 | return qvariant_cast<QCborArray>(v: variant).toJsonArray(); |
516 | case QMetaType::QCborMap: |
517 | return qvariant_cast<QCborMap>(v: variant).toJsonObject(); |
518 | #endif |
519 | default: |
520 | break; |
521 | } |
522 | QString string = variant.toString(); |
523 | if (string.isEmpty()) |
524 | return QJsonValue(); |
525 | return QJsonValue(string); |
526 | } |
527 | |
528 | /*! |
529 | Converts the value to a \l {QVariant::}{QVariant()}. |
530 | |
531 | The QJsonValue types will be converted as follows: |
532 | |
533 | \value Null QMetaType::Nullptr |
534 | \value Bool QMetaType::Bool |
535 | \value Double QMetaType::Double or QMetaType::LongLong |
536 | \value String QString |
537 | \value Array QVariantList |
538 | \value Object QVariantMap |
539 | \value Undefined \l {QVariant::}{QVariant()} |
540 | |
541 | \sa fromVariant() |
542 | */ |
543 | QVariant QJsonValue::toVariant() const |
544 | { |
545 | switch (t) { |
546 | case QCborValue::True: |
547 | return true; |
548 | case QCborValue::False: |
549 | return false; |
550 | case QCborValue::Integer: |
551 | return n; |
552 | case QCborValue::Double: |
553 | return toDouble(); |
554 | case QCborValue::String: |
555 | return toString(); |
556 | case QCborValue::Array: |
557 | return d ? |
558 | QJsonArray(d.data()).toVariantList() : |
559 | QVariantList(); |
560 | case QCborValue::Map: |
561 | return d ? |
562 | QJsonObject(d.data()).toVariantMap() : |
563 | QVariantMap(); |
564 | case QCborValue::Null: |
565 | return QVariant::fromValue(value: nullptr); |
566 | case QCborValue::Undefined: |
567 | default: |
568 | break; |
569 | } |
570 | return QVariant(); |
571 | } |
572 | |
573 | /*! |
574 | \enum QJsonValue::Type |
575 | |
576 | This enum describes the type of the JSON value. |
577 | |
578 | \value Null A Null value |
579 | \value Bool A boolean value. Use toBool() to convert to a bool. |
580 | \value Double A double. Use toDouble() to convert to a double. |
581 | \value String A string. Use toString() to convert to a QString. |
582 | \value Array An array. Use toArray() to convert to a QJsonArray. |
583 | \value Object An object. Use toObject() to convert to a QJsonObject. |
584 | \value Undefined The value is undefined. This is usually returned as an |
585 | error condition, when trying to read an out of bounds value |
586 | in an array or a non existent key in an object. |
587 | */ |
588 | |
589 | /*! |
590 | Returns the type of the value. |
591 | |
592 | \sa QJsonValue::Type |
593 | */ |
594 | QJsonValue::Type QJsonValue::type() const |
595 | { |
596 | switch (t) { |
597 | case QCborValue::Null: |
598 | return QJsonValue::Null; |
599 | case QCborValue::True: |
600 | case QCborValue::False: |
601 | return QJsonValue::Bool; |
602 | case QCborValue::Double: |
603 | case QCborValue::Integer: |
604 | return QJsonValue::Double; |
605 | case QCborValue::String: |
606 | return QJsonValue::String; |
607 | case QCborValue::Array: |
608 | return QJsonValue::Array; |
609 | case QCborValue::Map: |
610 | return QJsonValue::Object; |
611 | case QCborValue::Undefined: |
612 | default: |
613 | return QJsonValue::Undefined; |
614 | } |
615 | } |
616 | |
617 | /*! |
618 | Converts the value to a bool and returns it. |
619 | |
620 | If type() is not bool, the \a defaultValue will be returned. |
621 | */ |
622 | bool QJsonValue::toBool(bool defaultValue) const |
623 | { |
624 | switch (t) { |
625 | case QCborValue::True: |
626 | return true; |
627 | case QCborValue::False: |
628 | return false; |
629 | default: |
630 | return defaultValue; |
631 | } |
632 | } |
633 | |
634 | /*! |
635 | \since 5.2 |
636 | Converts the value to an int and returns it. |
637 | |
638 | If type() is not Double or the value is not a whole number, |
639 | the \a defaultValue will be returned. |
640 | */ |
641 | int QJsonValue::toInt(int defaultValue) const |
642 | { |
643 | switch (t) { |
644 | case QCborValue::Double: { |
645 | const double dbl = toDouble(); |
646 | int dblInt; |
647 | convertDoubleTo<int>(v: dbl, value: &dblInt); |
648 | return dbl == dblInt ? dblInt : defaultValue; |
649 | } |
650 | case QCborValue::Integer: |
651 | return (n <= qint64(std::numeric_limits<int>::max()) |
652 | && n >= qint64(std::numeric_limits<int>::min())) |
653 | ? n : defaultValue; |
654 | default: |
655 | return defaultValue; |
656 | } |
657 | } |
658 | |
659 | /*! |
660 | Converts the value to a double and returns it. |
661 | |
662 | If type() is not Double, the \a defaultValue will be returned. |
663 | */ |
664 | double QJsonValue::toDouble(double defaultValue) const |
665 | { |
666 | switch (t) { |
667 | case QCborValue::Double: { |
668 | double d; |
669 | memcpy(dest: &d, src: &n, n: sizeof(d)); |
670 | return d; |
671 | } |
672 | case QCborValue::Integer: |
673 | return n; |
674 | default: |
675 | return defaultValue; |
676 | } |
677 | } |
678 | |
679 | /*! |
680 | Converts the value to a QString and returns it. |
681 | |
682 | If type() is not String, the \a defaultValue will be returned. |
683 | */ |
684 | QString QJsonValue::toString(const QString &defaultValue) const |
685 | { |
686 | return (t == QCborValue::String && d) ? d->stringAt(idx: n) : defaultValue; |
687 | } |
688 | |
689 | /*! |
690 | Converts the value to a QString and returns it. |
691 | |
692 | If type() is not String, a null QString will be returned. |
693 | |
694 | \sa QString::isNull() |
695 | */ |
696 | QString QJsonValue::toString() const |
697 | { |
698 | return (t == QCborValue::String && d) ? d->stringAt(idx: n) : QString(); |
699 | } |
700 | |
701 | /*! |
702 | Converts the value to an array and returns it. |
703 | |
704 | If type() is not Array, the \a defaultValue will be returned. |
705 | */ |
706 | QJsonArray QJsonValue::toArray(const QJsonArray &defaultValue) const |
707 | { |
708 | if (t != QCborValue::Array || n >= 0 || !d) |
709 | return defaultValue; |
710 | |
711 | return QJsonArray(d.data()); |
712 | } |
713 | |
714 | /*! |
715 | \overload |
716 | |
717 | Converts the value to an array and returns it. |
718 | |
719 | If type() is not Array, a \l{QJsonArray::}{QJsonArray()} will be returned. |
720 | */ |
721 | QJsonArray QJsonValue::toArray() const |
722 | { |
723 | return toArray(defaultValue: QJsonArray()); |
724 | } |
725 | |
726 | /*! |
727 | Converts the value to an object and returns it. |
728 | |
729 | If type() is not Object, the \a defaultValue will be returned. |
730 | */ |
731 | QJsonObject QJsonValue::toObject(const QJsonObject &defaultValue) const |
732 | { |
733 | if (t != QCborValue::Map || n >= 0 || !d) |
734 | return defaultValue; |
735 | |
736 | return QJsonObject(d.data()); |
737 | } |
738 | |
739 | /*! |
740 | \overload |
741 | |
742 | Converts the value to an object and returns it. |
743 | |
744 | If type() is not Object, the \l {QJsonObject::}{QJsonObject()} will be returned. |
745 | */ |
746 | QJsonObject QJsonValue::toObject() const |
747 | { |
748 | return toObject(defaultValue: QJsonObject()); |
749 | } |
750 | |
751 | #if QT_STRINGVIEW_LEVEL < 2 |
752 | /*! |
753 | Returns a QJsonValue representing the value for the key \a key. |
754 | |
755 | Equivalent to calling toObject().value(key). |
756 | |
757 | The returned QJsonValue is QJsonValue::Undefined if the key does not exist, |
758 | or if isObject() is false. |
759 | |
760 | \since 5.10 |
761 | |
762 | \sa QJsonValue, QJsonValue::isUndefined(), QJsonObject |
763 | */ |
764 | const QJsonValue QJsonValue::operator[](const QString &key) const |
765 | { |
766 | return (*this)[QStringView(key)]; |
767 | } |
768 | #endif |
769 | |
770 | /*! |
771 | \overload |
772 | \since 5.14 |
773 | */ |
774 | const QJsonValue QJsonValue::operator[](QStringView key) const |
775 | { |
776 | if (!isObject()) |
777 | return QJsonValue(QJsonValue::Undefined); |
778 | |
779 | return toObject().value(key); |
780 | } |
781 | |
782 | /*! |
783 | \overload |
784 | \since 5.10 |
785 | */ |
786 | const QJsonValue QJsonValue::operator[](QLatin1String key) const |
787 | { |
788 | if (!isObject()) |
789 | return QJsonValue(QJsonValue::Undefined); |
790 | |
791 | return toObject().value(key); |
792 | } |
793 | |
794 | /*! |
795 | Returns a QJsonValue representing the value for index \a i. |
796 | |
797 | Equivalent to calling toArray().at(i). |
798 | |
799 | The returned QJsonValue is QJsonValue::Undefined, if \a i is out of bounds, |
800 | or if isArray() is false. |
801 | |
802 | \since 5.10 |
803 | |
804 | \sa QJsonValue, QJsonValue::isUndefined(), QJsonArray |
805 | */ |
806 | const QJsonValue QJsonValue::operator[](int i) const |
807 | { |
808 | if (!isArray()) |
809 | return QJsonValue(QJsonValue::Undefined); |
810 | |
811 | return toArray().at(i); |
812 | } |
813 | |
814 | /*! |
815 | Returns \c true if the value is equal to \a other. |
816 | */ |
817 | bool QJsonValue::operator==(const QJsonValue &other) const |
818 | { |
819 | if (t != other.t) |
820 | return false; |
821 | |
822 | switch (t) { |
823 | case QCborValue::Undefined: |
824 | case QCborValue::Null: |
825 | case QCborValue::True: |
826 | case QCborValue::False: |
827 | break; |
828 | case QCborValue::Double: |
829 | return toDouble() == other.toDouble(); |
830 | case QCborValue::Integer: |
831 | return n == other.n; |
832 | case QCborValue::String: |
833 | return toString() == other.toString(); |
834 | case QCborValue::Array: |
835 | if (!d) |
836 | return !other.d || other.d->elements.length() == 0; |
837 | if (!other.d) |
838 | return d->elements.length() == 0; |
839 | return QJsonArray(d.data()) == QJsonArray(other.d.data()); |
840 | case QCborValue::Map: |
841 | if (!d) |
842 | return !other.d || other.d->elements.length() == 0; |
843 | if (!other.d) |
844 | return d->elements.length() == 0; |
845 | return QJsonObject(d.data()) == QJsonObject(other.d.data()); |
846 | default: |
847 | return false; |
848 | } |
849 | return true; |
850 | } |
851 | |
852 | /*! |
853 | Returns \c true if the value is not equal to \a other. |
854 | */ |
855 | bool QJsonValue::operator!=(const QJsonValue &other) const |
856 | { |
857 | return !(*this == other); |
858 | } |
859 | |
860 | /*! |
861 | \internal |
862 | */ |
863 | void QJsonValue::detach() |
864 | { |
865 | d.detach(); |
866 | } |
867 | |
868 | |
869 | /*! |
870 | \class QJsonValueRef |
871 | \inmodule QtCore |
872 | \reentrant |
873 | \brief The QJsonValueRef class is a helper class for QJsonValue. |
874 | |
875 | \internal |
876 | |
877 | \ingroup json |
878 | |
879 | When you get an object of type QJsonValueRef, if you can assign to it, |
880 | the assignment will apply to the character in the string from |
881 | which you got the reference. That is its whole purpose in life. |
882 | |
883 | You can use it exactly in the same way as a reference to a QJsonValue. |
884 | |
885 | The QJsonValueRef becomes invalid once modifications are made to the |
886 | string: if you want to keep the character, copy it into a QJsonValue. |
887 | |
888 | Most of the QJsonValue member functions also exist in QJsonValueRef. |
889 | However, they are not explicitly documented here. |
890 | */ |
891 | |
892 | |
893 | QJsonValueRef &QJsonValueRef::operator =(const QJsonValue &val) |
894 | { |
895 | if (is_object) |
896 | o->setValueAt(i: index, val); |
897 | else |
898 | a->replace(i: index, value: val); |
899 | |
900 | return *this; |
901 | } |
902 | |
903 | QJsonValueRef &QJsonValueRef::operator =(const QJsonValueRef &ref) |
904 | { |
905 | if (is_object) |
906 | o->setValueAt(i: index, val: ref); |
907 | else |
908 | a->replace(i: index, value: ref); |
909 | |
910 | return *this; |
911 | } |
912 | |
913 | QVariant QJsonValueRef::toVariant() const |
914 | { |
915 | return toValue().toVariant(); |
916 | } |
917 | |
918 | QJsonArray QJsonValueRef::toArray() const |
919 | { |
920 | return toValue().toArray(); |
921 | } |
922 | |
923 | QJsonObject QJsonValueRef::toObject() const |
924 | { |
925 | return toValue().toObject(); |
926 | } |
927 | |
928 | QJsonValue QJsonValueRef::toValue() const |
929 | { |
930 | if (!is_object) |
931 | return a->at(i: index); |
932 | return o->valueAt(i: index); |
933 | } |
934 | |
935 | uint qHash(const QJsonValue &value, uint seed) |
936 | { |
937 | switch (value.type()) { |
938 | case QJsonValue::Null: |
939 | return qHash(nullptr, seed); |
940 | case QJsonValue::Bool: |
941 | return qHash(t: value.toBool(), seed); |
942 | case QJsonValue::Double: |
943 | return qHash(key: value.toDouble(), seed); |
944 | case QJsonValue::String: |
945 | return qHash(key: value.toString(), seed); |
946 | case QJsonValue::Array: |
947 | return qHash(array: value.toArray(), seed); |
948 | case QJsonValue::Object: |
949 | return qHash(object: value.toObject(), seed); |
950 | case QJsonValue::Undefined: |
951 | return seed; |
952 | } |
953 | Q_UNREACHABLE(); |
954 | return 0; |
955 | } |
956 | |
957 | #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) |
958 | QDebug operator<<(QDebug dbg, const QJsonValue &o) |
959 | { |
960 | QDebugStateSaver saver(dbg); |
961 | switch (o.type()) { |
962 | case QJsonValue::Undefined: |
963 | dbg << "QJsonValue(undefined)" ; |
964 | break; |
965 | case QJsonValue::Null: |
966 | dbg << "QJsonValue(null)" ; |
967 | break; |
968 | case QJsonValue::Bool: |
969 | dbg.nospace() << "QJsonValue(bool, " << o.toBool() << ')'; |
970 | break; |
971 | case QJsonValue::Double: |
972 | dbg.nospace() << "QJsonValue(double, " << o.toDouble() << ')'; |
973 | break; |
974 | case QJsonValue::String: |
975 | dbg.nospace() << "QJsonValue(string, " << o.toString() << ')'; |
976 | break; |
977 | case QJsonValue::Array: |
978 | dbg.nospace() << "QJsonValue(array, " ; |
979 | dbg << o.toArray(); |
980 | dbg << ')'; |
981 | break; |
982 | case QJsonValue::Object: |
983 | dbg.nospace() << "QJsonValue(object, " ; |
984 | dbg << o.toObject(); |
985 | dbg << ')'; |
986 | break; |
987 | } |
988 | return dbg; |
989 | } |
990 | #endif |
991 | |
992 | #ifndef QT_NO_DATASTREAM |
993 | QDataStream &operator<<(QDataStream &stream, const QJsonValue &v) |
994 | { |
995 | quint8 type = v.type(); |
996 | stream << type; |
997 | switch (type) { |
998 | case QJsonValue::Undefined: |
999 | case QJsonValue::Null: |
1000 | break; |
1001 | case QJsonValue::Bool: |
1002 | stream << v.toBool(); |
1003 | break; |
1004 | case QJsonValue::Double: |
1005 | stream << v.toDouble(); |
1006 | break; |
1007 | case QJsonValue::String: |
1008 | stream << v.toString(); |
1009 | break; |
1010 | case QJsonValue::Array: |
1011 | stream << v.toArray(); |
1012 | break; |
1013 | case QJsonValue::Object: |
1014 | stream << v.toObject(); |
1015 | break; |
1016 | } |
1017 | return stream; |
1018 | } |
1019 | |
1020 | QDataStream &operator>>(QDataStream &stream, QJsonValue &v) |
1021 | { |
1022 | quint8 type; |
1023 | stream >> type; |
1024 | switch (type) { |
1025 | case QJsonValue::Undefined: |
1026 | case QJsonValue::Null: |
1027 | v = QJsonValue{QJsonValue::Type(type)}; |
1028 | break; |
1029 | case QJsonValue::Bool: { |
1030 | bool b; |
1031 | stream >> b; |
1032 | v = QJsonValue(b); |
1033 | break; |
1034 | } case QJsonValue::Double: { |
1035 | double d; |
1036 | stream >> d; |
1037 | v = QJsonValue{d}; |
1038 | break; |
1039 | } case QJsonValue::String: { |
1040 | QString s; |
1041 | stream >> s; |
1042 | v = QJsonValue{s}; |
1043 | break; |
1044 | } |
1045 | case QJsonValue::Array: { |
1046 | QJsonArray a; |
1047 | stream >> a; |
1048 | v = QJsonValue{a}; |
1049 | break; |
1050 | } |
1051 | case QJsonValue::Object: { |
1052 | QJsonObject o; |
1053 | stream >> o; |
1054 | v = QJsonValue{o}; |
1055 | break; |
1056 | } |
1057 | default: { |
1058 | stream.setStatus(QDataStream::ReadCorruptData); |
1059 | v = QJsonValue{QJsonValue::Undefined}; |
1060 | } |
1061 | } |
1062 | return stream; |
1063 | } |
1064 | #endif |
1065 | |
1066 | QT_END_NAMESPACE |
1067 | |