qjsondocument.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/corelib/json/qjsondocument.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
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 "qjsonwriter_p.h"-
48#include "qjsonparser_p.h"-
49#include "qjson_p.h"-
50-
51QT_BEGIN_NAMESPACE-
52-
53/*! \class QJsonDocument-
54 \inmodule QtCore-
55 \ingroup json-
56 \ingroup shared-
57 \reentrant-
58 \since 5.0-
59-
60 \brief The QJsonDocument class provides a way to read and write JSON documents.-
61-
62 QJsonDocument is a class that wraps a complete JSON document and can read and-
63 write this document both from a UTF-8 encoded text based representation as well-
64 as Qt's own binary format.-
65-
66 A JSON document can be converted from its text-based representation to a QJsonDocument-
67 using QJsonDocument::fromJson(). toJson() converts it back to text. The parser is very-
68 fast and efficient and converts the JSON to the binary representation used by Qt.-
69-
70 Validity of the parsed document can be queried with !isNull()-
71-
72 A document can be queried as to whether it contains an array or an object using isArray()-
73 and isObject(). The array or object contained in the document can be retrieved using-
74 array() or object() and then read or manipulated.-
75-
76 A document can also be created from a stored binary representation using fromBinaryData() or-
77 fromRawData().-
78-
79 \sa {JSON Support in Qt}, {JSON Save Game Example}-
80*/-
81-
82/*!-
83 * Constructs an empty and invalid document.-
84 */-
85QJsonDocument::QJsonDocument()-
86 : d(0)-
87{-
88}-
89-
90/*!-
91 * Creates a QJsonDocument from \a object.-
92 */-
93QJsonDocument::QJsonDocument(const QJsonObject &object)-
94 : d(0)-
95{-
96 setObject(object);-
97}-
98-
99/*!-
100 * Constructs a QJsonDocument from \a array.-
101 */-
102QJsonDocument::QJsonDocument(const QJsonArray &array)-
103 : d(0)-
104{-
105 setArray(array);-
106}-
107-
108/*!-
109 \internal-
110 */-
111QJsonDocument::QJsonDocument(QJsonPrivate::Data *data)-
112 : d(data)-
113{-
114 Q_ASSERT(d);-
115 d->ref.ref();-
116}-
117-
118/*!-
119 Deletes the document.-
120-
121 Binary data set with fromRawData is not freed.-
122 */-
123QJsonDocument::~QJsonDocument()-
124{-
125 if (d && !d->ref.deref())-
126 delete d;-
127}-
128-
129/*!-
130 * Creates a copy of the \a other document.-
131 */-
132QJsonDocument::QJsonDocument(const QJsonDocument &other)-
133{-
134 d = other.d;-
135 if (d)-
136 d->ref.ref();-
137}-
138-
139/*!-
140 * Assigns the \a other document to this QJsonDocument.-
141 * Returns a reference to this object.-
142 */-
143QJsonDocument &QJsonDocument::operator =(const QJsonDocument &other)-
144{-
145 if (d != other.d) {-
146 if (d && !d->ref.deref())-
147 delete d;-
148 d = other.d;-
149 if (d)-
150 d->ref.ref();-
151 }-
152-
153 return *this;-
154}-
155-
156/*! \enum QJsonDocument::DataValidation-
157-
158 This value is used to tell QJsonDocument whether to validate the binary data-
159 when converting to a QJsonDocument using fromBinaryData() or fromRawData().-
160-
161 \value Validate Validate the data before using it. This is the default.-
162 \value BypassValidation Bypasses data validation. Only use if you received the-
163 data from a trusted place and know it's valid, as using of invalid data can crash-
164 the application.-
165 */-
166-
167/*!-
168 Creates a QJsonDocument that uses the first \a size bytes from-
169 \a data. It assumes \a data contains a binary encoded JSON document.-
170 The created document does not take ownership of \a data and the caller-
171 has to guarantee that \a data will not be deleted or modified as long as-
172 any QJsonDocument, QJsonObject or QJsonArray still references the data.-
173-
174 \a data has to be aligned to a 4 byte boundary.-
175-
176 \a validation decides whether the data is checked for validity before being used.-
177 By default the data is validated. If the \a data is not valid, the method returns-
178 a null document.-
179-
180 Returns a QJsonDocument representing the data.-
181-
182 \sa rawData(), fromBinaryData(), isNull(), DataValidation-
183 */-
184QJsonDocument QJsonDocument::fromRawData(const char *data, int size, DataValidation validation)-
185{-
186 if (quintptr(data) & 3) {
quintptr(data) & 3Description
TRUEnever evaluated
FALSEnever evaluated
0
187 qWarning() <<("QJsonDocument::fromRawData: data has to have 4 byte alignment";);-
188 return QJsonDocument();
never executed: return QJsonDocument();
0
189 }if (size < (int)(sizeof(QJsonPrivate::Header) + sizeof(QJsonPrivate::Base)))-
return QJsonDocument();
190-
191 QJsonPrivate::Data *d = new QJsonPrivate::Data((char *)data, size);-
192 d->ownsData = false;-
193-
194 if (validation != BypassValidation && !d->valid()) {
validation != BypassValidationDescription
TRUEnever evaluated
FALSEnever evaluated
!d->valid()Description
TRUEnever evaluated
FALSEnever evaluated
0
195 delete d;-
196 return QJsonDocument();
never executed: return QJsonDocument();
0
197 }-
198-
199 return QJsonDocument(d);
never executed: return QJsonDocument(d);
0
200}-
201-
202/*!-
203 Returns the raw binary representation of the data-
204 \a size will contain the size of the returned data.-
205-
206 This method is useful to e.g. stream the JSON document-
207 in it's binary form to a file.-
208 */-
209const char *QJsonDocument::rawData(int *size) const-
210{-
211 if (!d) {-
212 *size = 0;-
213 return 0;-
214 }-
215 *size = d->alloc;-
216 return d->rawData;-
217}-
218-
219/*!-
220 Creates a QJsonDocument from \a data.-
221-
222 \a validation decides whether the data is checked for validity before being used.-
223 By default the data is validated. If the \a data is not valid, the method returns-
224 a null document.-
225-
226 \sa toBinaryData(), fromRawData(), isNull(), DataValidation-
227 */-
228QJsonDocument QJsonDocument::fromBinaryData(const QByteArray &data, DataValidation validation)-
229{-
230 if (data.size() < (int)(sizeof(QJsonPrivate::Header) + sizeof(QJsonPrivate::Base)))-
231 return QJsonDocument();-
232-
233 QJsonPrivate::Header h;-
234 memcpy(&h, data.constData(), sizeof(QJsonPrivate::Header));-
235 QJsonPrivate::Base root;-
236 memcpy(&root, data.constData() + sizeof(QJsonPrivate::Header), sizeof(QJsonPrivate::Base));-
237-
238 // do basic checks here, so we don't try to allocate more memory than we can.-
239 if (h.tag != QJsonDocument::BinaryFormatTag || h.version != 1u ||-
240 sizeof(QJsonPrivate::Header) + root.size > (uint)data.size())-
241 return QJsonDocument();-
242-
243 const uint size = sizeof(QJsonPrivate::Header) + root.size;-
244 char *raw = (char *)malloc(size);-
245 if (!raw)-
246 return QJsonDocument();-
247-
248 memcpy(raw, data.constData(), size);-
249 QJsonPrivate::Data *d = new QJsonPrivate::Data(raw, size);-
250-
251 if (validation != BypassValidation && !d->valid()) {-
252 delete d;-
253 return QJsonDocument();-
254 }-
255-
256 return QJsonDocument(d);-
257}-
258-
259/*!-
260 Creates a QJsonDocument from the QVariant \a variant.-
261-
262 If the \a variant contains any other type than a QVariantMap,-
263 QVariantList or QStringList, the returned document is invalid.-
264-
265 \sa toVariant()-
266 */-
267QJsonDocument QJsonDocument::fromVariant(const QVariant &variant)-
268{-
269 QJsonDocument doc;-
270 if (variant.type() == QVariant::Map) {-
271 doc.setObject(QJsonObject::fromVariantMap(variant.toMap()));-
272 } else if (variant.type() == QVariant::List) {-
273 doc.setArray(QJsonArray::fromVariantList(variant.toList()));-
274 } else if (variant.type() == QVariant::StringList) {-
275 doc.setArray(QJsonArray::fromStringList(variant.toStringList()));-
276 }-
277 return doc;-
278}-
279-
280/*!-
281 Returns a QVariant representing the Json document.-
282-
283 The returned variant will be a QVariantList if the document is-
284 a QJsonArray and a QVariantMap if the document is a QJsonObject.-
285-
286 \sa fromVariant(), QJsonValue::toVariant()-
287 */-
288QVariant QJsonDocument::toVariant() const-
289{-
290 if (!d)-
291 return QVariant();-
292-
293 if (d->header->root()->isArray())-
294 return QJsonArray(d, static_cast<QJsonPrivate::Array *>(d->header->root())).toVariantList();-
295 else-
296 return QJsonObject(d, static_cast<QJsonPrivate::Object *>(d->header->root())).toVariantMap();-
297}-
298-
299/*!-
300 Converts the QJsonDocument to a UTF-8 encoded JSON document.-
301-
302 \sa fromJson()-
303 */-
304#ifndef QT_JSON_READONLY-
305QByteArray QJsonDocument::toJson() const-
306{-
307 return toJson(Indented);-
308}-
309#endif-
310-
311/*!-
312 \enum QJsonDocument::JsonFormat-
313-
314 This value defines the format of the JSON byte array produced-
315 when converting to a QJsonDocument using toJson().-
316-
317 \value Indented Defines human readable output as follows:-
318 \code-
319 {-
320 "Array": [-
321 true,-
322 999,-
323 "string"-
324 ],-
325 "Key": "Value",-
326 "null": null-
327 }-
328 \endcode-
329-
330 \value Compact Defines a compact output as follows:-
331 \code-
332 {"Array":[true,999,"string"],"Key":"Value","null":null}-
333 \endcode-
334 */-
335-
336/*!-
337 Converts the QJsonDocument to a UTF-8 encoded JSON document in the provided \a format.-
338-
339 \sa fromJson(), JsonFormat-
340 */-
341#ifndef QT_JSON_READONLY-
342QByteArray QJsonDocument::toJson(JsonFormat format) const-
343{-
344 if (!d)-
345 return QByteArray();-
346-
347 QByteArray json;-
348-
349 if (d->header->root()->isArray())-
350 QJsonPrivate::Writer::arrayToJson(static_cast<QJsonPrivate::Array *>(d->header->root()), json, 0, (format == Compact));-
351 else-
352 QJsonPrivate::Writer::objectToJson(static_cast<QJsonPrivate::Object *>(d->header->root()), json, 0, (format == Compact));-
353-
354 return json;-
355}-
356#endif-
357-
358/*!-
359 Parses \a json as a UTF-8 encoded JSON document, and creates a QJsonDocument-
360 from it.-
361-
362 Returns a valid (non-null) QJsonDocument if the parsing succeeds. If it fails,-
363 the returned document will be null, and the optional \a error variable will contain-
364 further details about the error.-
365-
366 \sa toJson(), QJsonParseError, isNull()-
367 */-
368QJsonDocument QJsonDocument::fromJson(const QByteArray &json, QJsonParseError *error)-
369{-
370 QJsonPrivate::Parser parser(json.constData(), json.length());-
371 return parser.parse(error);-
372}-
373-
374/*!-
375 Returns \c true if the document doesn't contain any data.-
376 */-
377bool QJsonDocument::isEmpty() const-
378{-
379 if (!d)-
380 return true;-
381-
382 return false;-
383}-
384-
385/*!-
386 Returns a binary representation of the document.-
387-
388 The binary representation is also the native format used internally in Qt,-
389 and is very efficient and fast to convert to and from.-
390-
391 The binary format can be stored on disk and interchanged with other applications-
392 or computers. fromBinaryData() can be used to convert it back into a-
393 JSON document.-
394-
395 \sa fromBinaryData()-
396 */-
397QByteArray QJsonDocument::toBinaryData() const-
398{-
399 if (!d || !d->rawData)-
400 return QByteArray();-
401-
402 return QByteArray(d->rawData, d->header->root()->size + sizeof(QJsonPrivate::Header));-
403}-
404-
405/*!-
406 Returns \c true if the document contains an array.-
407-
408 \sa array(), isObject()-
409 */-
410bool QJsonDocument::isArray() const-
411{-
412 if (!d)-
413 return false;-
414-
415 QJsonPrivate::Header *h = (QJsonPrivate::Header *)d->rawData;-
416 return h->root()->isArray();-
417}-
418-
419/*!-
420 Returns \c true if the document contains an object.-
421-
422 \sa object(), isArray()-
423 */-
424bool QJsonDocument::isObject() const-
425{-
426 if (!d)-
427 return false;-
428-
429 QJsonPrivate::Header *h = (QJsonPrivate::Header *)d->rawData;-
430 return h->root()->isObject();-
431}-
432-
433/*!-
434 Returns the QJsonObject contained in the document.-
435-
436 Returns an empty object if the document contains an-
437 array.-
438-
439 \sa isObject(), array(), setObject()-
440 */-
441QJsonObject QJsonDocument::object() const-
442{-
443 if (d) {-
444 QJsonPrivate::Base *b = d->header->root();-
445 if (b->isObject())-
446 return QJsonObject(d, static_cast<QJsonPrivate::Object *>(b));-
447 }-
448 return QJsonObject();-
449}-
450-
451/*!-
452 Returns the QJsonArray contained in the document.-
453-
454 Returns an empty array if the document contains an-
455 object.-
456-
457 \sa isArray(), object(), setArray()-
458 */-
459QJsonArray QJsonDocument::array() const-
460{-
461 if (d) {-
462 QJsonPrivate::Base *b = d->header->root();-
463 if (b->isArray())-
464 return QJsonArray(d, static_cast<QJsonPrivate::Array *>(b));-
465 }-
466 return QJsonArray();-
467}-
468-
469/*!-
470 Sets \a object as the main object of this document.-
471-
472 \sa setArray(), object()-
473 */-
474void QJsonDocument::setObject(const QJsonObject &object)-
475{-
476 if (d && !d->ref.deref())-
477 delete d;-
478-
479 d = object.d;-
480-
481 if (!d) {-
482 d = new QJsonPrivate::Data(0, QJsonValue::Object);-
483 } else if (d->compactionCounter || object.o != d->header->root()) {-
484 QJsonObject o(object);-
485 if (d->compactionCounter)-
486 o.compact();-
487 else-
488 o.detach2();-
489 d = o.d;-
490 d->ref.ref();-
491 return;-
492 }-
493 d->ref.ref();-
494}-
495-
496/*!-
497 Sets \a array as the main object of this document.-
498-
499 \sa setObject(), array()-
500 */-
501void QJsonDocument::setArray(const QJsonArray &array)-
502{-
503 if (d && !d->ref.deref())-
504 delete d;-
505-
506 d = array.d;-
507-
508 if (!d) {-
509 d = new QJsonPrivate::Data(0, QJsonValue::Array);-
510 } else if (d->compactionCounter || array.a != d->header->root()) {-
511 QJsonArray a(array);-
512 if (d->compactionCounter)-
513 a.compact();-
514 else-
515 a.detach2();-
516 d = a.d;-
517 d->ref.ref();-
518 return;-
519 }-
520 d->ref.ref();-
521}-
522-
523/*!-
524 Returns \c true if the \a other document is equal to this document.-
525 */-
526bool QJsonDocument::operator==(const QJsonDocument &other) const-
527{-
528 if (d == other.d)-
529 return true;-
530-
531 if (!d || !other.d)-
532 return false;-
533-
534 if (d->header->root()->isArray() != other.d->header->root()->isArray())-
535 return false;-
536-
537 if (d->header->root()->isObject())-
538 return QJsonObject(d, static_cast<QJsonPrivate::Object *>(d->header->root()))-
539 == QJsonObject(other.d, static_cast<QJsonPrivate::Object *>(other.d->header->root()));-
540 else-
541 return QJsonArray(d, static_cast<QJsonPrivate::Array *>(d->header->root()))-
542 == QJsonArray(other.d, static_cast<QJsonPrivate::Array *>(other.d->header->root()));-
543}-
544-
545/*!-
546 \fn bool QJsonDocument::operator!=(const QJsonDocument &other) const-
547-
548 returns \c true if \a other is not equal to this document-
549 */-
550-
551/*!-
552 returns \c true if this document is null.-
553-
554 Null documents are documents created through the default constructor.-
555-
556 Documents created from UTF-8 encoded text or the binary format are-
557 validated during parsing. If validation fails, the returned document-
558 will also be null.-
559 */-
560bool QJsonDocument::isNull() const-
561{-
562 return (d == 0);-
563}-
564-
565#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)-
566QDebug operator<<(QDebug dbg, const QJsonDocument &o)-
567{-
568 QDebugStateSaver saver(dbg);-
569 if (!o.d) {-
570 dbg << "QJsonDocument()";-
571 return dbg;-
572 }-
573 QByteArray json;-
574 if (o.d->header->root()->isArray())-
575 QJsonPrivate::Writer::arrayToJson(static_cast<QJsonPrivate::Array *>(o.d->header->root()), json, 0, true);-
576 else-
577 QJsonPrivate::Writer::objectToJson(static_cast<QJsonPrivate::Object *>(o.d->header->root()), json, 0, true);-
578 dbg.nospace() << "QJsonDocument("-
579 << json.constData() // print as utf-8 string without extra quotation marks-
580 << ')';-
581 return dbg;-
582}-
583#endif-
584-
585QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9