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 <qjsondocument.h> |
41 | #include <qjsonobject.h> |
42 | #include <qjsonvalue.h> |
43 | #include <qjsonarray.h> |
44 | #include <qstringlist.h> |
45 | #include <qvariant.h> |
46 | #include <qdebug.h> |
47 | #include <qcbormap.h> |
48 | #include <qcborarray.h> |
49 | #include "qcborvalue_p.h" |
50 | #include "qjsonwriter_p.h" |
51 | #include "qjsonparser_p.h" |
52 | #include "qjson_p.h" |
53 | #include "qdatastream.h" |
54 | |
55 | #if QT_CONFIG(binaryjson) |
56 | #include "qbinaryjson_p.h" |
57 | #include "qbinaryjsonobject_p.h" |
58 | #include "qbinaryjsonarray_p.h" |
59 | #endif |
60 | |
61 | #include <private/qmemory_p.h> |
62 | |
63 | QT_BEGIN_NAMESPACE |
64 | |
65 | /*! \class QJsonDocument |
66 | \inmodule QtCore |
67 | \ingroup json |
68 | \ingroup shared |
69 | \reentrant |
70 | \since 5.0 |
71 | |
72 | \brief The QJsonDocument class provides a way to read and write JSON documents. |
73 | |
74 | QJsonDocument is a class that wraps a complete JSON document and can read and |
75 | write this document both from a UTF-8 encoded text based representation as well |
76 | as Qt's own binary format. |
77 | |
78 | A JSON document can be converted from its text-based representation to a QJsonDocument |
79 | using QJsonDocument::fromJson(). toJson() converts it back to text. The parser is very |
80 | fast and efficient and converts the JSON to the binary representation used by Qt. |
81 | |
82 | Validity of the parsed document can be queried with !isNull() |
83 | |
84 | A document can be queried as to whether it contains an array or an object using isArray() |
85 | and isObject(). The array or object contained in the document can be retrieved using |
86 | array() or object() and then read or manipulated. |
87 | |
88 | A document can also be created from a stored binary representation using fromBinaryData() or |
89 | fromRawData(). |
90 | |
91 | \sa {JSON Support in Qt}, {JSON Save Game Example} |
92 | */ |
93 | |
94 | |
95 | class QJsonDocumentPrivate |
96 | { |
97 | Q_DISABLE_COPY_MOVE(QJsonDocumentPrivate); |
98 | public: |
99 | QJsonDocumentPrivate() = default; |
100 | QJsonDocumentPrivate(QCborValue data) : value(std::move(data)) {} |
101 | ~QJsonDocumentPrivate() |
102 | { |
103 | if (rawData) |
104 | free(ptr: rawData); |
105 | } |
106 | |
107 | QCborValue value; |
108 | char *rawData = nullptr; |
109 | uint rawDataSize = 0; |
110 | |
111 | void clearRawData() |
112 | { |
113 | if (rawData) { |
114 | free(ptr: rawData); |
115 | rawData = nullptr; |
116 | rawDataSize = 0; |
117 | } |
118 | } |
119 | }; |
120 | |
121 | /*! |
122 | * Constructs an empty and invalid document. |
123 | */ |
124 | QJsonDocument::QJsonDocument() |
125 | : d(nullptr) |
126 | { |
127 | } |
128 | |
129 | /*! |
130 | * Creates a QJsonDocument from \a object. |
131 | */ |
132 | QJsonDocument::QJsonDocument(const QJsonObject &object) |
133 | : d(nullptr) |
134 | { |
135 | setObject(object); |
136 | } |
137 | |
138 | /*! |
139 | * Constructs a QJsonDocument from \a array. |
140 | */ |
141 | QJsonDocument::QJsonDocument(const QJsonArray &array) |
142 | : d(nullptr) |
143 | { |
144 | setArray(array); |
145 | } |
146 | |
147 | /*! |
148 | \internal |
149 | */ |
150 | QJsonDocument::QJsonDocument(const QCborValue &data) |
151 | : d(qt_make_unique<QJsonDocumentPrivate>(args: data)) |
152 | { |
153 | Q_ASSERT(d); |
154 | } |
155 | |
156 | /*! |
157 | Deletes the document. |
158 | |
159 | Binary data set with fromRawData is not freed. |
160 | */ |
161 | QJsonDocument::~QJsonDocument() = default; |
162 | |
163 | /*! |
164 | * Creates a copy of the \a other document. |
165 | */ |
166 | QJsonDocument::QJsonDocument(const QJsonDocument &other) |
167 | { |
168 | if (other.d) { |
169 | if (!d) |
170 | d = qt_make_unique<QJsonDocumentPrivate>(); |
171 | d->value = other.d->value; |
172 | } else { |
173 | d.reset(); |
174 | } |
175 | } |
176 | |
177 | QJsonDocument::QJsonDocument(QJsonDocument &&other) noexcept |
178 | : d(std::move(other.d)) |
179 | { |
180 | } |
181 | |
182 | void QJsonDocument::swap(QJsonDocument &other) noexcept |
183 | { |
184 | qSwap(value1&: d, value2&: other.d); |
185 | } |
186 | |
187 | /*! |
188 | * Assigns the \a other document to this QJsonDocument. |
189 | * Returns a reference to this object. |
190 | */ |
191 | QJsonDocument &QJsonDocument::operator =(const QJsonDocument &other) |
192 | { |
193 | if (this != &other) { |
194 | if (other.d) { |
195 | if (!d) |
196 | d = qt_make_unique<QJsonDocumentPrivate>(); |
197 | else |
198 | d->clearRawData(); |
199 | d->value = other.d->value; |
200 | } else { |
201 | d.reset(); |
202 | } |
203 | } |
204 | return *this; |
205 | } |
206 | |
207 | /*! |
208 | \fn QJsonDocument::QJsonDocument(QJsonDocument &&other) |
209 | \since 5.10 |
210 | |
211 | Move-constructs a QJsonDocument from \a other. |
212 | */ |
213 | |
214 | /*! |
215 | \fn QJsonDocument &QJsonDocument::operator =(QJsonDocument &&other) |
216 | \since 5.10 |
217 | |
218 | Move-assigns \a other to this document. |
219 | */ |
220 | |
221 | /*! |
222 | \fn void QJsonDocument::swap(QJsonDocument &other) |
223 | \since 5.10 |
224 | |
225 | Swaps the document \a other with this. This operation is very fast and never fails. |
226 | */ |
227 | |
228 | |
229 | /*! \enum QJsonDocument::DataValidation |
230 | |
231 | This value is used to tell QJsonDocument whether to validate the binary data |
232 | when converting to a QJsonDocument using fromBinaryData() or fromRawData(). |
233 | |
234 | \value Validate Validate the data before using it. This is the default. |
235 | \value BypassValidation Bypasses data validation. Only use if you received the |
236 | data from a trusted place and know it's valid, as using of invalid data can crash |
237 | the application. |
238 | */ |
239 | |
240 | #if QT_CONFIG(binaryjson) && QT_DEPRECATED_SINCE(5, 15) |
241 | /*! |
242 | \deprecated |
243 | |
244 | Creates a QJsonDocument that uses the first \a size bytes from |
245 | \a data. It assumes \a data contains a binary encoded JSON document. |
246 | The created document does not take ownership of \a data. The data is |
247 | copied into a different data structure, and the original data can be |
248 | deleted or modified afterwards. |
249 | |
250 | \a data has to be aligned to a 4 byte boundary. |
251 | |
252 | \a validation decides whether the data is checked for validity before being used. |
253 | By default the data is validated. If the \a data is not valid, the method returns |
254 | a null document. |
255 | |
256 | Returns a QJsonDocument representing the data. |
257 | |
258 | \note Deprecated in Qt 5.15. The binary JSON encoding is only retained for backwards |
259 | compatibility. It is undocumented and restrictive in the maximum size of JSON |
260 | documents that can be encoded. Qt JSON types can be converted to Qt CBOR types, |
261 | which can in turn be serialized into the CBOR binary format and vice versa. The |
262 | CBOR format is a well-defined and less restrictive binary representation for a |
263 | superset of JSON. |
264 | |
265 | \note Before Qt 5.15, the caller had to guarantee that \a data would not be |
266 | deleted or modified as long as any QJsonDocument, QJsonObject or QJsonArray |
267 | still referenced the data. From Qt 5.15 on, this is not necessary anymore. |
268 | |
269 | \sa rawData(), fromBinaryData(), isNull(), DataValidation, QCborValue |
270 | */ |
271 | QJsonDocument QJsonDocument::fromRawData(const char *data, int size, DataValidation validation) |
272 | { |
273 | if (quintptr(data) & 3) { |
274 | qWarning(msg: "QJsonDocument::fromRawData: data has to have 4 byte alignment" ); |
275 | return QJsonDocument(); |
276 | } |
277 | |
278 | if (size < 0 || uint(size) < sizeof(QBinaryJsonPrivate::Header) + sizeof(QBinaryJsonPrivate::Base)) |
279 | return QJsonDocument(); |
280 | |
281 | std::unique_ptr<QBinaryJsonPrivate::ConstData> binaryData |
282 | = qt_make_unique<QBinaryJsonPrivate::ConstData>(args&: data, args&: size); |
283 | |
284 | return (validation == BypassValidation || binaryData->isValid()) |
285 | ? binaryData->toJsonDocument() |
286 | : QJsonDocument(); |
287 | } |
288 | |
289 | /*! |
290 | \deprecated |
291 | |
292 | Returns the raw binary representation of the data |
293 | \a size will contain the size of the returned data. |
294 | |
295 | This method is useful to e.g. stream the JSON document |
296 | in its binary form to a file. |
297 | |
298 | \note Deprecated in Qt 5.15. The binary JSON encoding is only retained for backwards |
299 | compatibility. It is undocumented and restrictive in the maximum size of JSON |
300 | documents that can be encoded. Qt JSON types can be converted to Qt CBOR types, |
301 | which can in turn be serialized into the CBOR binary format and vice versa. The |
302 | CBOR format is a well-defined and less restrictive binary representation for a |
303 | superset of JSON. |
304 | |
305 | \sa QCborValue |
306 | */ |
307 | const char *QJsonDocument::rawData(int *size) const |
308 | { |
309 | if (!d) { |
310 | *size = 0; |
311 | return nullptr; |
312 | } |
313 | |
314 | if (!d->rawData) { |
315 | if (isObject()) { |
316 | QBinaryJsonObject o = QBinaryJsonObject::fromJsonObject(object: object()); |
317 | d->rawData = o.takeRawData(size: &(d->rawDataSize)); |
318 | } else { |
319 | QBinaryJsonArray a = QBinaryJsonArray::fromJsonArray(array: array()); |
320 | d->rawData = a.takeRawData(size: &(d->rawDataSize)); |
321 | } |
322 | } |
323 | |
324 | // It would be quite miraculous if not, as we should have hit the 128MB limit then. |
325 | Q_ASSERT(d->rawDataSize <= uint(std::numeric_limits<int>::max())); |
326 | |
327 | *size = d->rawDataSize; |
328 | return d->rawData; |
329 | } |
330 | |
331 | /*! |
332 | \deprecated |
333 | Creates a QJsonDocument from \a data. |
334 | |
335 | \a validation decides whether the data is checked for validity before being used. |
336 | By default the data is validated. If the \a data is not valid, the method returns |
337 | a null document. |
338 | |
339 | \note Deprecated in Qt 5.15. The binary JSON encoding is only retained for backwards |
340 | compatibility. It is undocumented and restrictive in the maximum size of JSON |
341 | documents that can be encoded. Qt JSON types can be converted to Qt CBOR types, |
342 | which can in turn be serialized into the CBOR binary format and vice versa. The |
343 | CBOR format is a well-defined and less restrictive binary representation for a |
344 | superset of JSON. |
345 | |
346 | \sa toBinaryData(), fromRawData(), isNull(), DataValidation, QCborValue |
347 | */ |
348 | QJsonDocument QJsonDocument::fromBinaryData(const QByteArray &data, DataValidation validation) |
349 | { |
350 | if (uint(data.size()) < sizeof(QBinaryJsonPrivate::Header) + sizeof(QBinaryJsonPrivate::Base)) |
351 | return QJsonDocument(); |
352 | |
353 | QBinaryJsonPrivate::Header h; |
354 | memcpy(dest: &h, src: data.constData(), n: sizeof(QBinaryJsonPrivate::Header)); |
355 | QBinaryJsonPrivate::Base root; |
356 | memcpy(dest: &root, src: data.constData() + sizeof(QBinaryJsonPrivate::Header), |
357 | n: sizeof(QBinaryJsonPrivate::Base)); |
358 | |
359 | const uint size = sizeof(QBinaryJsonPrivate::Header) + root.size; |
360 | if (h.tag != QJsonDocument::BinaryFormatTag || h.version != 1U || size > uint(data.size())) |
361 | return QJsonDocument(); |
362 | |
363 | std::unique_ptr<QBinaryJsonPrivate::ConstData> d |
364 | = qt_make_unique<QBinaryJsonPrivate::ConstData>(args: data.constData(), args: size); |
365 | |
366 | return (validation == BypassValidation || d->isValid()) |
367 | ? d->toJsonDocument() |
368 | : QJsonDocument(); |
369 | } |
370 | |
371 | /*! |
372 | \deprecated |
373 | Returns a binary representation of the document. |
374 | |
375 | The binary representation is also the native format used internally in Qt, |
376 | and is very efficient and fast to convert to and from. |
377 | |
378 | The binary format can be stored on disk and interchanged with other applications |
379 | or computers. fromBinaryData() can be used to convert it back into a |
380 | JSON document. |
381 | |
382 | \note Deprecated in Qt 5.15. The binary JSON encoding is only retained for backwards |
383 | compatibility. It is undocumented and restrictive in the maximum size of JSON |
384 | documents that can be encoded. Qt JSON types can be converted to Qt CBOR types, |
385 | which can in turn be serialized into the CBOR binary format and vice versa. The |
386 | CBOR format is a well-defined and less restrictive binary representation for a |
387 | superset of JSON. |
388 | |
389 | \sa fromBinaryData(), QCborValue |
390 | */ |
391 | QByteArray QJsonDocument::toBinaryData() const |
392 | { |
393 | int size = 0; |
394 | QT_WARNING_PUSH |
395 | QT_WARNING_DISABLE_DEPRECATED |
396 | const char *raw = rawData(size: &size); |
397 | QT_WARNING_POP |
398 | return QByteArray(raw, size); |
399 | } |
400 | #endif // QT_CONFIG(binaryjson) && QT_DEPRECATED_SINCE(5, 15) |
401 | |
402 | /*! |
403 | Creates a QJsonDocument from the QVariant \a variant. |
404 | |
405 | If the \a variant contains any other type than a QVariantMap, |
406 | QVariantHash, QVariantList or QStringList, the returned document is invalid. |
407 | |
408 | \sa toVariant() |
409 | */ |
410 | QJsonDocument QJsonDocument::fromVariant(const QVariant &variant) |
411 | { |
412 | QJsonDocument doc; |
413 | |
414 | switch (variant.userType()) { |
415 | case QMetaType::QVariantMap: |
416 | doc.setObject(QJsonObject::fromVariantMap(map: variant.toMap())); |
417 | break; |
418 | case QMetaType::QVariantHash: |
419 | doc.setObject(QJsonObject::fromVariantHash(map: variant.toHash())); |
420 | break; |
421 | case QMetaType::QVariantList: |
422 | doc.setArray(QJsonArray::fromVariantList(list: variant.toList())); |
423 | break; |
424 | case QMetaType::QStringList: |
425 | doc.d = qt_make_unique<QJsonDocumentPrivate>(); |
426 | doc.d->value = QCborArray::fromStringList(list: variant.toStringList()); |
427 | break; |
428 | default: |
429 | break; |
430 | } |
431 | return doc; |
432 | } |
433 | |
434 | /*! |
435 | Returns a QVariant representing the Json document. |
436 | |
437 | The returned variant will be a QVariantList if the document is |
438 | a QJsonArray and a QVariantMap if the document is a QJsonObject. |
439 | |
440 | \sa fromVariant(), QJsonValue::toVariant() |
441 | */ |
442 | QVariant QJsonDocument::toVariant() const |
443 | { |
444 | if (!d) |
445 | return QVariant(); |
446 | |
447 | QCborContainerPrivate *container = QJsonPrivate::Value::container(v: d->value); |
448 | if (d->value.isArray()) |
449 | return QJsonArray(container).toVariantList(); |
450 | return QJsonObject(container).toVariantMap(); |
451 | } |
452 | |
453 | /*! |
454 | Converts the QJsonDocument to an indented, UTF-8 encoded JSON document. |
455 | |
456 | \sa fromJson() |
457 | */ |
458 | #if !defined(QT_JSON_READONLY) || defined(Q_CLANG_QDOC) |
459 | QByteArray QJsonDocument::toJson() const |
460 | { |
461 | return toJson(format: Indented); |
462 | } |
463 | #endif |
464 | |
465 | /*! |
466 | \enum QJsonDocument::JsonFormat |
467 | \since 5.1 |
468 | |
469 | This value defines the format of the JSON byte array produced |
470 | when converting to a QJsonDocument using toJson(). |
471 | |
472 | \value Indented Defines human readable output as follows: |
473 | \snippet code/src_corelib_serialization_qjsondocument.cpp 0 |
474 | |
475 | \value Compact Defines a compact output as follows: |
476 | \snippet code/src_corelib_serialization_qjsondocument.cpp 1 |
477 | */ |
478 | |
479 | /*! |
480 | \since 5.1 |
481 | Converts the QJsonDocument to a UTF-8 encoded JSON document in the provided \a format. |
482 | |
483 | \sa fromJson(), JsonFormat |
484 | */ |
485 | #if !defined(QT_JSON_READONLY) || defined(Q_CLANG_QDOC) |
486 | QByteArray QJsonDocument::toJson(JsonFormat format) const |
487 | { |
488 | QByteArray json; |
489 | if (!d) |
490 | return json; |
491 | |
492 | const QCborContainerPrivate *container = QJsonPrivate::Value::container(v: d->value); |
493 | if (d->value.isArray()) |
494 | QJsonPrivate::Writer::arrayToJson(a: container, json, indent: 0, compact: (format == Compact)); |
495 | else |
496 | QJsonPrivate::Writer::objectToJson(o: container, json, indent: 0, compact: (format == Compact)); |
497 | |
498 | return json; |
499 | } |
500 | #endif |
501 | |
502 | /*! |
503 | Parses \a json as a UTF-8 encoded JSON document, and creates a QJsonDocument |
504 | from it. |
505 | |
506 | Returns a valid (non-null) QJsonDocument if the parsing succeeds. If it fails, |
507 | the returned document will be null, and the optional \a error variable will contain |
508 | further details about the error. |
509 | |
510 | \sa toJson(), QJsonParseError, isNull() |
511 | */ |
512 | QJsonDocument QJsonDocument::fromJson(const QByteArray &json, QJsonParseError *error) |
513 | { |
514 | QJsonPrivate::Parser parser(json.constData(), json.length()); |
515 | QJsonDocument result; |
516 | const QCborValue val = parser.parse(error); |
517 | if (val.isArray() || val.isMap()) { |
518 | result.d = qt_make_unique<QJsonDocumentPrivate>(); |
519 | result.d->value = val; |
520 | } |
521 | return result; |
522 | } |
523 | |
524 | /*! |
525 | Returns \c true if the document doesn't contain any data. |
526 | */ |
527 | bool QJsonDocument::isEmpty() const |
528 | { |
529 | if (!d) |
530 | return true; |
531 | |
532 | return false; |
533 | } |
534 | |
535 | /*! |
536 | Returns \c true if the document contains an array. |
537 | |
538 | \sa array(), isObject() |
539 | */ |
540 | bool QJsonDocument::isArray() const |
541 | { |
542 | if (!d) |
543 | return false; |
544 | |
545 | return d->value.isArray(); |
546 | } |
547 | |
548 | /*! |
549 | Returns \c true if the document contains an object. |
550 | |
551 | \sa object(), isArray() |
552 | */ |
553 | bool QJsonDocument::isObject() const |
554 | { |
555 | if (!d) |
556 | return false; |
557 | |
558 | return d->value.isMap(); |
559 | } |
560 | |
561 | /*! |
562 | Returns the QJsonObject contained in the document. |
563 | |
564 | Returns an empty object if the document contains an |
565 | array. |
566 | |
567 | \sa isObject(), array(), setObject() |
568 | */ |
569 | QJsonObject QJsonDocument::object() const |
570 | { |
571 | if (isObject()) { |
572 | if (auto container = QJsonPrivate::Value::container(v: d->value)) |
573 | return QJsonObject(container); |
574 | } |
575 | return QJsonObject(); |
576 | } |
577 | |
578 | /*! |
579 | Returns the QJsonArray contained in the document. |
580 | |
581 | Returns an empty array if the document contains an |
582 | object. |
583 | |
584 | \sa isArray(), object(), setArray() |
585 | */ |
586 | QJsonArray QJsonDocument::array() const |
587 | { |
588 | if (isArray()) { |
589 | if (auto container = QJsonPrivate::Value::container(v: d->value)) |
590 | return QJsonArray(container); |
591 | } |
592 | return QJsonArray(); |
593 | } |
594 | |
595 | /*! |
596 | Sets \a object as the main object of this document. |
597 | |
598 | \sa setArray(), object() |
599 | */ |
600 | void QJsonDocument::setObject(const QJsonObject &object) |
601 | { |
602 | if (!d) |
603 | d = qt_make_unique<QJsonDocumentPrivate>(); |
604 | else |
605 | d->clearRawData(); |
606 | |
607 | d->value = QCborValue::fromJsonValue(v: object); |
608 | } |
609 | |
610 | /*! |
611 | Sets \a array as the main object of this document. |
612 | |
613 | \sa setObject(), array() |
614 | */ |
615 | void QJsonDocument::setArray(const QJsonArray &array) |
616 | { |
617 | if (!d) |
618 | d = qt_make_unique<QJsonDocumentPrivate>(); |
619 | else |
620 | d->clearRawData(); |
621 | |
622 | d->value = QCborValue::fromJsonValue(v: array); |
623 | } |
624 | |
625 | #if QT_STRINGVIEW_LEVEL < 2 |
626 | /*! |
627 | Returns a QJsonValue representing the value for the key \a key. |
628 | |
629 | Equivalent to calling object().value(key). |
630 | |
631 | The returned QJsonValue is QJsonValue::Undefined if the key does not exist, |
632 | or if isObject() is false. |
633 | |
634 | \since 5.10 |
635 | |
636 | \sa QJsonValue, QJsonValue::isUndefined(), QJsonObject |
637 | */ |
638 | const QJsonValue QJsonDocument::operator[](const QString &key) const |
639 | { |
640 | return (*this)[QStringView(key)]; |
641 | } |
642 | #endif |
643 | |
644 | /*! |
645 | \overload |
646 | \since 5.14 |
647 | */ |
648 | const QJsonValue QJsonDocument::operator[](QStringView key) const |
649 | { |
650 | if (!isObject()) |
651 | return QJsonValue(QJsonValue::Undefined); |
652 | |
653 | return QJsonPrivate::Value::fromTrustedCbor(v: d->value.toMap().value(key)); |
654 | } |
655 | |
656 | /*! |
657 | \overload |
658 | \since 5.10 |
659 | */ |
660 | const QJsonValue QJsonDocument::operator[](QLatin1String key) const |
661 | { |
662 | if (!isObject()) |
663 | return QJsonValue(QJsonValue::Undefined); |
664 | |
665 | return QJsonPrivate::Value::fromTrustedCbor(v: d->value.toMap().value(key)); |
666 | } |
667 | |
668 | /*! |
669 | Returns a QJsonValue representing the value for index \a i. |
670 | |
671 | Equivalent to calling array().at(i). |
672 | |
673 | The returned QJsonValue is QJsonValue::Undefined, if \a i is out of bounds, |
674 | or if isArray() is false. |
675 | |
676 | \since 5.10 |
677 | |
678 | \sa QJsonValue, QJsonValue::isUndefined(), QJsonArray |
679 | */ |
680 | const QJsonValue QJsonDocument::operator[](int i) const |
681 | { |
682 | if (!isArray()) |
683 | return QJsonValue(QJsonValue::Undefined); |
684 | |
685 | return QJsonPrivate::Value::fromTrustedCbor(v: d->value.toArray().at(i)); |
686 | } |
687 | |
688 | /*! |
689 | Returns \c true if the \a other document is equal to this document. |
690 | */ |
691 | bool QJsonDocument::operator==(const QJsonDocument &other) const |
692 | { |
693 | if (d && other.d) |
694 | return d->value == other.d->value; |
695 | return !d == !other.d; |
696 | } |
697 | |
698 | /*! |
699 | \fn bool QJsonDocument::operator!=(const QJsonDocument &other) const |
700 | |
701 | returns \c true if \a other is not equal to this document |
702 | */ |
703 | |
704 | /*! |
705 | returns \c true if this document is null. |
706 | |
707 | Null documents are documents created through the default constructor. |
708 | |
709 | Documents created from UTF-8 encoded text or the binary format are |
710 | validated during parsing. If validation fails, the returned document |
711 | will also be null. |
712 | */ |
713 | bool QJsonDocument::isNull() const |
714 | { |
715 | return (d == nullptr); |
716 | } |
717 | |
718 | #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) |
719 | QDebug operator<<(QDebug dbg, const QJsonDocument &o) |
720 | { |
721 | QDebugStateSaver saver(dbg); |
722 | if (!o.d) { |
723 | dbg << "QJsonDocument()" ; |
724 | return dbg; |
725 | } |
726 | QByteArray json; |
727 | const QCborContainerPrivate *container = QJsonPrivate::Value::container(v: o.d->value); |
728 | if (o.d->value.isArray()) |
729 | QJsonPrivate::Writer::arrayToJson(a: container, json, indent: 0, compact: true); |
730 | else |
731 | QJsonPrivate::Writer::objectToJson(o: container, json, indent: 0, compact: true); |
732 | dbg.nospace() << "QJsonDocument(" |
733 | << json.constData() // print as utf-8 string without extra quotation marks |
734 | << ')'; |
735 | return dbg; |
736 | } |
737 | #endif |
738 | |
739 | #ifndef QT_NO_DATASTREAM |
740 | QDataStream &operator<<(QDataStream &stream, const QJsonDocument &doc) |
741 | { |
742 | stream << doc.toJson(format: QJsonDocument::Compact); |
743 | return stream; |
744 | } |
745 | |
746 | QDataStream &operator>>(QDataStream &stream, QJsonDocument &doc) |
747 | { |
748 | QByteArray buffer; |
749 | stream >> buffer; |
750 | QJsonParseError parseError{}; |
751 | doc = QJsonDocument::fromJson(json: buffer, error: &parseError); |
752 | if (parseError.error && !buffer.isEmpty()) |
753 | stream.setStatus(QDataStream::ReadCorruptData); |
754 | return stream; |
755 | } |
756 | #endif |
757 | |
758 | QT_END_NAMESPACE |
759 | |