Qx v0.5.7
Qt Extensions Library
Loading...
Searching...
No Matches
qx-json.h
Go to the documentation of this file.
1#ifndef QX_JSON_H
2#define QX_JSON_H
3
4// Shared Lib Support
5#include "qx/core/qx_core_export.h"
6
7// Qt Includes
8#include <QString>
9#include <QJsonValueRef>
10#include <QJsonObject>
11#include <QJsonArray>
12#include <QJsonDocument>
13#include <QFile>
14#include <QFileInfo>
15
16// Intra-component Includes
18#include "qx/core/qx-error.h"
19
20// Extra-component Includes
23
24// TODO: Improve JsonError to allow for more context, i.e. the error
25// can note the full "path" in the JSON tree where the error occurred
26
27//-Macros------------------------------------------------------------------
29#define __QX_JSON_META_STRUCT_INSIDE(meta_tuple) \
30 template <typename StructT> \
31 struct QxJsonMetaStructInside \
32 { \
33 static inline constexpr auto memberMetadata() \
34 { \
35 return meta_tuple; \
36 } \
37 }
38
39#define __QX_JSON_META_STRUCT_OUTSIDE(self_type, meta_tuple) \
40namespace QxJson \
41{ \
42 template <typename StructT> \
43 struct QxJsonMetaStructOutside<self_type, StructT> \
44 { \
45 static inline constexpr auto memberMetadata() \
46 { \
47 return meta_tuple; \
48 } \
49 }; \
50}
51
54#define QX_JSON_MEMBER(member) QxJsonPrivate::makeMemberMetadata<#member>(&StructT::member)
55#define QX_JSON_MEMBER_ALIASED(member, key) QxJsonPrivate::makeMemberMetadata<key>(&StructT::member)
56
57#define QX_JSON_STRUCT(...) __QX_JSON_META_STRUCT_INSIDE(std::make_tuple(QX_FOR_EACH_DELIM(QX_JSON_MEMBER, __VA_ARGS__)))
58#define QX_JSON_STRUCT_X(...) __QX_JSON_META_STRUCT_INSIDE(std::make_tuple(__VA_ARGS__))
59
60#define QX_JSON_STRUCT_OUTSIDE(Struct, ...) __QX_JSON_META_STRUCT_OUTSIDE(Struct, std::make_tuple(QX_FOR_EACH_DELIM(QX_JSON_MEMBER, __VA_ARGS__)))
61#define QX_JSON_STRUCT_OUTSIDE_X(Struct, ...) __QX_JSON_META_STRUCT_OUTSIDE(Struct, std::make_tuple(__VA_ARGS__))
62
63/*
64 * TODO: Create an "inside" version of this macro and its underlying functions, though it's tricky
65 * given clang/GCCs issues with non-namespace explicit template specializations so either a dummy
66 * template parameter will need to be used (to make it technically a partial specialization) or
67 * the specializations themselves will still need to be outside the struct (second macro), while
68 * the declaration of the inner override struct (first macro, e.g. QX_JSON_DECLARE_MEMBER_OVERRIDES(); )
69 * is inside
70 */
71#define QX_JSON_MEMBER_OVERRIDE(Struct, member, ...) \
72namespace QxJson \
73{ \
74 template<> \
75 struct MemberOverrideCoverter<Struct, #member> \
76 { \
77 __VA_ARGS__\
78 }; \
79}
80
81namespace QxJson
82{
83
84class QX_CORE_EXPORT File
85{
86private:
87 QString mIdentifier;
88 QString mFileError;
89
90public:
91 File(const QString& filename, const QString& fileError = {});
92 File(const QFile& docFile, const QString& fileError = {});
93 File(const QFileInfo& docFile, const QString& fileError = {});
94
95 QString string() const;
96};
97
98class QX_CORE_EXPORT Document
99{
100private:
101 QString mName;
102
103public:
104 Document(const QString& name = {});
105
106 QString string() const;
107};
108
109class QX_CORE_EXPORT Object
110{
111public:
112 Object();
113
114 QString string() const;
115};
116
117class QX_CORE_EXPORT ObjectKey
118{
119private:
120 QString mName;
121
122public:
123 ObjectKey(const QString& name);
124
125 QString string() const;
126};
127
128class QX_CORE_EXPORT Array
129{
130public:
131 Array();
132
133 QString string() const;
134};
135
136class QX_CORE_EXPORT ArrayElement
137{
138private:
139 uint mElement;
140
141public:
142 ArrayElement(uint element);
143
144 QString string() const;
145};
146
147using ContextNode = std::variant<File, Document, Object, ObjectKey, Array, ArrayElement>;
148
149} // namespace QxJson
150
151namespace Qx
152{
153
154class QX_CORE_EXPORT JsonError final : public AbstractError<"Qx::JsonError", 5>
155{
156//-Class Enums-------------------------------------------------------------
157public:
158 enum Form
159 {
160 NoError = 0,
162 TypeMismatch,
163 EmptyDoc,
164 InvalidValue,
165 MissingFile,
166 InaccessibleFile,
167 FileReadError
168 };
169
170//-Class Variables-------------------------------------------------------------
171private:
172 static inline const QHash<Form, QString> ERR_STRINGS{
173 {NoError, u""_s},
174 {MissingKey, u"The key does not exist."_s},
175 {TypeMismatch, u"Value type mismatch."_s},
176 {EmptyDoc, u"The document is empty."_s},
177 {InvalidValue, u"Invalid value for type."_s},
178 {MissingFile, u"File does not exist."_s},
179 {InaccessibleFile, u"Cannot open the file."_s},
180 {FileReadError, u"File read error."_s}
181 };
182
183//-Instance Variables-------------------------------------------------------------
184private:
185 QString mAction;
186 Form mForm;
188
189//-Constructor-----------------------------------------------------------------
190public:
191 JsonError();
192 JsonError(const QString& a, Form f);
193
194//-Instance Functions-------------------------------------------------------------
195private:
196 quint32 deriveValue() const override;
197 QString derivePrimary() const override;
198 QString deriveSecondary() const override;
199 QString deriveDetails() const override;
200
201public:
202 bool isValid() const;
203 QString action() const;
204 Form form() const;
205 QList<QxJson::ContextNode> context() const;
206 JsonError& withContext(const QxJson::ContextNode& node);
207};
208
209} // namespace Qx
210
212namespace QxJsonPrivate
213{
214//-Namespace Variables---------------------------------------------------
215static inline const QString ERR_CONV_TYPE = u"JSON Error: Converting value to %1"_s;
216static inline const QString ERR_NO_KEY = u"JSON Error: Could not retrieve key '%1'."_s;
217static inline const QString ERR_PARSE_DOC = u"JSON Error: Could not parse JSON document."_s;
218static inline const QString ERR_READ_FILE = u"JSON Error: Could not read JSON file."_s;
219
220//-Structs---------------------------------------------------------------
221template<Qx::StringLiteral MemberN, typename MemberT, class Struct>
222struct MemberMetadata
223{
224 constexpr static Qx::StringLiteral M_NAME = MemberN;
225 typedef MemberT M_TYPE;
226 MemberT Struct::* mPtr;
227};
228
229//-Functions-------------------------------------------------------------
230template <Qx::StringLiteral N, typename T, class S>
231constexpr MemberMetadata<N, T, S> makeMemberMetadata(T S::*memberPtr)
232{
233 return {memberPtr};
234}
235
236template<typename T> [[maybe_unused]] static inline QString typeString() = delete;
237template<typename T> [[maybe_unused]] static inline bool isType(const QJsonValue& v) = delete;
238template<typename T> [[maybe_unused]] static inline T toType(const QJsonValue& v) = delete;
239
240template<> inline QString typeString<bool>() { return u"bool"_s; };
241template<> inline QString typeString<double>() { return u"double"_s; };
242template<> inline QString typeString<QString>() { return u"string"_s; };
243template<> inline QString typeString<QJsonArray>() { return u"array"_s; };
244template<> inline QString typeString<QJsonObject>() { return u"object"_s; };
245
246template<> inline bool isType<bool>(const QJsonValue& v) { return v.isBool(); };
247template<> inline bool isType<double>(const QJsonValue& v) { return v.isDouble(); };
248template<> inline bool isType<QString>(const QJsonValue& v) { return v.isString(); };
249template<> inline bool isType<QJsonArray>(const QJsonValue& v) { return v.isArray(); };
250template<> inline bool isType<QJsonObject>(const QJsonValue& v) { return v.isObject(); };
251
252template<> inline bool toType<bool>(const QJsonValue& v) { return v.toBool(); };
253template<> inline double toType<double>(const QJsonValue& v) { return v.toDouble(); };
254template<> inline QString toType<QString>(const QJsonValue& v) { return v.toString(); };
255template<> inline QJsonArray toType<QJsonArray>(const QJsonValue& v) { return v.toArray(); };
256template<> inline QJsonObject toType<QJsonObject>(const QJsonValue& v) { return v.toObject(); };
257
258} // namespace QxJsonPrivate
261namespace QxJson
262{
263//-Structs---------------------------------------------------------------
264template<typename T>
266
267template<class Struct, Qx::StringLiteral member>
269
270template<typename SelfType, typename DelayedSelfType>
272
273//-Concepts--------------------------------------------------------------
274
275// TODO: Document these concepts
276template<typename T>
278
279template<typename T>
280concept json_struct_inside = requires {
281 T::template QxJsonMetaStructInside<T>::memberMetadata();
282};
283
284template<typename T>
285concept json_struct_outside = requires {
286 QxJsonMetaStructOutside<T, T>::memberMetadata();
287};
288
289template<typename T>
292
293template<typename T>
294concept json_convertible = requires(T& tValue) {
295 { Converter<T>::fromJson(tValue, QJsonValue()) } -> std::same_as<Qx::JsonError>;
296};
297
298template<class K, typename T, Qx::StringLiteral N>
299concept json_override_convertible = requires(T& tValue) {
300 { MemberOverrideCoverter<K, N>::fromJson(tValue, QJsonValue()) } -> std::same_as<Qx::JsonError>;
301};
302
303template<typename Key, class Value>
304Key keygen(const Value& value) = delete;
305
306template<typename Key, class Value>
307concept json_keyable = requires(const Value& v) {
308 { keygen<Key, Value>(v) } -> std::same_as<Key>;
309};
310
311template<typename T>
314
315template<typename T>
319
320template<typename T>
323
324template<typename T>
327
328} // namespace QxJson
329
331namespace QxJsonPrivate
332{
333//-Functions-------------------------------------------------------------
334/* These helpers are required as a form on indirection within
335 *
336 * template<typename T>
337 * requires json_struct<T>
338 * struct Converter<T> {...}
339 *
340 * That functions makes/made use of 'if constexpr' statements that contain
341 * references to a type in their true branches that doesn't exist if the
342 * false branches are taken. Different compilers seem to discard the untaken
343 * branch of the value dependent statement at different stages as it compiled
344 * fine with MSVC and a newer version of GCC, but not clang or older GCC versions.
345 * To clarify, compilation would fail due to the type in the not-yet-discarded
346 * branch not being declared.
347 *
348 * Putting the reference of the potentially undeclared types behind these functions
349 * that always exist solves the issue.
350 */
351template<class K>
353constexpr auto getMemberMeta()
354{
355 return K::template QxJsonMetaStructInside<K>::memberMetadata();
356}
357
358template<class K>
360constexpr auto getMemberMeta()
361{
363}
364
365template<class K, typename T, Qx::StringLiteral N>
367Qx::JsonError performOverrideConversion(T& value, const QJsonValue& jv)
368{
370}
371
372template<typename T>
374Qx::JsonError performRegularConversion(T& value, const QJsonValue& jv)
375{
376 return QxJson::Converter<T>::fromJson(value, jv);
377}
380} // namespace QxJsonPrivate
381
382
383namespace QxJson
384{
385//-Default Converter Specializations-------------------------------------
387template<typename T>
388 requires qjson_type<T>
389struct Converter<T>
390{
391 static Qx::JsonError fromJson(T& value, const QJsonValue& jValue)
392 {
393 if(!QxJsonPrivate::isType<T>(jValue))
394 return Qx::JsonError(QxJsonPrivate::ERR_CONV_TYPE.arg(QxJsonPrivate::typeString<T>()), Qx::JsonError::TypeMismatch);
395
396 value = QxJsonPrivate::toType<T>(jValue);
397 return Qx::JsonError();
398 }
399};
400
401template<typename T>
402 requires json_struct<T>
403struct Converter<T>
404{
405 static Qx::JsonError fromJson(T& value, const QJsonValue& jValue)
406 {
407 if(!jValue.isObject())
408 return Qx::JsonError(QxJsonPrivate::ERR_CONV_TYPE.arg(QxJsonPrivate::typeString<QJsonObject>()), Qx::JsonError::TypeMismatch)
410
411 // Underlying object
412 QJsonObject jObject = jValue.toObject();
413
414 // Error tracker
415 Qx::JsonError cnvError;
416
417 // Get member metadata tuple
418 constexpr auto memberMetas = QxJsonPrivate::getMemberMeta<T>();
419
420 // "Iterate" over each tuple element via std::apply, with a fold expression
421 // utilizing && which short-circuits. This allows us to "break" the loop
422 // upon a member conversion failure as single return of false in the inner-most
423 // lambda will trigger the short-circuit.
424 std::apply([&](auto&&... memberMeta) constexpr {
425 // Fold expression
426 ([&]{
427 // Meta
428 static constexpr auto mName = std::remove_reference<decltype(memberMeta)>::type::M_NAME;
429 constexpr QLatin1StringView mKey(mName.value);
430 using mType = typename std::remove_reference<decltype(memberMeta)>::type::M_TYPE;
431 auto mPtr = memberMeta.mPtr;
432
433 // Get value from key
434 if(!jObject.contains(mKey))
435 {
436 if constexpr(json_optional<mType>)
437 {
438 value.*mPtr = std::nullopt;
439 return true;
440 }
441 else
442 {
443 cnvError = Qx::JsonError(QxJsonPrivate::ERR_NO_KEY.arg(mKey), Qx::JsonError::MissingKey)
445 return false;
446 }
447 }
448 QJsonValue mValue = jObject.value(mKey);
449
450 // Convert value
451 if constexpr(json_override_convertible<T, mType, mName>)
452 cnvError = QxJsonPrivate::performOverrideConversion<T, mType, mName>(value.*mPtr, mValue);
453 else
454 cnvError = QxJsonPrivate::performRegularConversion<mType>(value.*mPtr, mValue);
455
457 return !cnvError.isValid();
458 }() && ...);
459 }, memberMetas);
460
461 return cnvError;
462 }
463};
464
465template<typename T>
466 requires json_collective<T>
467struct Converter<T>
468{
469 using E = typename T::value_type;
470
471 static Qx::JsonError fromJson(T& value, const QJsonValue& jValue)
472 {
473 // Reset buffer
474 value.clear();
475
476 if(!jValue.isArray())
477 {
478 return Qx::JsonError(QxJsonPrivate::ERR_CONV_TYPE.arg(QxJsonPrivate::typeString<QJsonArray>()), Qx::JsonError::TypeMismatch)
480 }
481
482 // Underlying Array
483 QJsonArray jArray = jValue.toArray();
484
485 // Error tracking
486 Qx::JsonError cnvError;
487
488 // Convert all
489 for(auto i = 0; i < jArray.count(); ++i)
490 {
491 E converted;
492 if(cnvError = Converter<E>::fromJson(converted, jArray[i]); cnvError.isValid())
493 {
494 value.clear();
496 }
497
498 value << converted;
499 }
500
501 return Qx::JsonError();
502 }
503};
504
505template<typename T>
506 requires json_associative<T>
507struct Converter<T>
508{
509 static Qx::JsonError fromJson(T& value, const QJsonValue& jValue)
510 {
511 using K = typename T::key_type;
512 using V = typename T::mapped_type;
513
514 // Reset buffer
515 value.clear();
516
517 if(!jValue.isArray())
518 {
519 return Qx::JsonError(QxJsonPrivate::ERR_CONV_TYPE.arg(QxJsonPrivate::typeString<QJsonArray>()), Qx::JsonError::TypeMismatch)
521 }
522 // Underlying Array
523 QJsonArray jArray = jValue.toArray();
524
525 // Error tracking
526 Qx::JsonError cnvError;
527
528 // Convert all
529 for(auto i = 0; i < jArray.count(); ++i)
530 {
531 V converted;
532 if(cnvError = Converter<V>::fromJson(converted, jArray[i]); cnvError.isValid())
533 {
534 value.clear();
536 }
537
538 value.insert(keygen<K, V>(converted), converted);
539 }
540
541 return Qx::JsonError();
542 }
543};
544
545template<typename T>
546 requires json_optional<T>
547struct Converter<T>
548{
549 using O = typename T::value_type;
550
551 static Qx::JsonError fromJson(T& value, const QJsonValue& jValue)
552 {
553 O opt;
554 Qx::JsonError je = Converter<O>::fromJson(opt, jValue);
555
556 if(!je.isValid())
557 value = std::move(opt);
558
559 return je;
560 }
561};
562
563template<typename T>
564 requires std::integral<T> && (!std::same_as<T, bool>)
565struct Converter<T>
566{
567 static Qx::JsonError fromJson(T& value, const QJsonValue& jValue)
568 {
569 if(!jValue.isDouble())
570 return Qx::JsonError(QxJsonPrivate::ERR_CONV_TYPE.arg(QxJsonPrivate::typeString<double>()), Qx::JsonError::TypeMismatch);
571
572 value = static_cast<T>(jValue.toDouble());
573 return Qx::JsonError();
574 }
575};
578} // namespace QxJson
579
580namespace Qx
581{
582
583//-Concepts (cont.)-------------------------------------------------------------------------------------------------
584template<typename T>
587
588//-Classes---------------------------------------------------------------------------------------------------------
589class QX_CORE_EXPORT QJsonParseErrorAdapter: public Qx::AbstractError<"QJsonParseError", 500>
590{
591//-Class Variables-------------------------------------------------------------------------------------
592private:
593 static inline const QString OFFSET_STR = u"Position: %1."_s;
594
595//-Instance Variables-------------------------------------------------------------------------------------
596private:
597 const QJsonParseError& mErrorRef;
598
599//-Constructor---------------------------------------------------------------------------------------------
600public:
604
605//-Instance Functions-------------------------------------------------------------------------------------
606private:
607 quint32 deriveValue() const override;
608 QString derivePrimary() const override;
609 QString deriveSecondary() const override;
610};
611
612//-Functions-------------------------------------------------------------------------------------------------------
613template<typename T>
615JsonError parseJson(T& parsed, const QJsonObject& obj)
616{
617 // Use QJsonValue for semi-type erasure
618 QJsonValue objAsValue(obj);
619
620 return QxJson::Converter<T>::fromJson(parsed, objAsValue);
621}
622
623template<typename T>
625JsonError parseJson(T& parsed, const QJsonArray& array)
626{
627 // Use QJsonValue for semi-type erasure
628 QJsonValue arrayAsValue(array);
629
630 return QxJson::Converter<T>::fromJson(parsed, array);
631}
632
633template<typename T>
634 requires json_root<T>
635JsonError parseJson(T& parsed, const QJsonDocument& doc)
636{
637 if(doc.isEmpty())
638 return JsonError(QxJsonPrivate::ERR_PARSE_DOC, JsonError::EmptyDoc).withContext(QxJson::Document());
639
640 if constexpr(QxJson::json_containing<T>)
641 {
642 if(!doc.isArray())
643 return JsonError(QxJsonPrivate::ERR_PARSE_DOC, JsonError::TypeMismatch).withContext(QxJson::Document());
644
645 return parseJson(parsed, doc.array()).withContext(QxJson::Document());
646 }
647 else
648 {
649 if(!doc.isObject())
650 return JsonError(QxJsonPrivate::ERR_PARSE_DOC, JsonError::TypeMismatch).withContext(QxJson::Document());
651
652 return parseJson(parsed, doc.object()).withContext(QxJson::Document());
653 }
654}
655
656template<typename T>
657 requires json_root<T>
658JsonError parseJson(T& parsed, QFile& file)
659{
660 if(!file.exists())
661 return JsonError(QxJsonPrivate::ERR_READ_FILE, JsonError::MissingFile).withContext(QxJson::File(file.fileName()));
662
663 // Close and re-open file if missing required mode
664 if(!file.isReadable())
665 {
666 if(file.isOpen())
667 file.close();
668
669 if(!file.open(QIODevice::ReadOnly))
670 return JsonError(QxJsonPrivate::ERR_READ_FILE, JsonError::InaccessibleFile).withContext(QxJson::File(file.fileName(), file.errorString()));
671 }
672
673 // Close file when finished
674 QScopeGuard fileGuard([&file]{ file.close(); });
675
676 // Read data
677 QByteArray jsonData = file.readAll();
678 if(jsonData.isEmpty())
679 {
680 if(file.error() != QFileDevice::NoError)
681 return JsonError(QxJsonPrivate::ERR_READ_FILE, JsonError::FileReadError).withContext(QxJson::File(file.fileName(), file.errorString()));
682 else
683 return JsonError(QxJsonPrivate::ERR_READ_FILE, JsonError::EmptyDoc).withContext(QxJson::File(file.fileName()));
684 }
685
686 // Basic parse
687 QJsonParseError jpe;
688 QJsonDocument jd = QJsonDocument::fromJson(jsonData, &jpe);
689
690 if(jpe.error != jpe.NoError)
691 return JsonError(QxJsonPrivate::ERR_READ_FILE, JsonError::FileReadError).withContext(QxJson::File(file.fileName(), jpe.errorString()));
692
693 // True parse
694 return parseJson(parsed, jd).withContext(QxJson::File(file.fileName()));
695}
696
697template<typename T>
698 requires json_root<T>
699JsonError parseJson(T& parsed, const QString& filePath)
700{
701 QFile file(filePath);
702
703 return parseJson(parsed, file);
704}
705
706QX_CORE_EXPORT QList<QJsonValue> findAllValues(const QJsonValue& rootValue, QStringView key);
707QX_CORE_EXPORT QString asString(const QJsonValue& value);
708
709} // namespace Qx
711
712#endif // QX_JSON_H
The array element key class represents a JSON Array element node for use in error contexts.
Definition qx-json.h:137
The array class represents a JSON array node for use in error contexts.
Definition qx-json.h:129
The document class represents a JSON document node for use in error contexts.
Definition qx-json.h:99
The file class represents a JSON file node for use in error contexts.
Definition qx-json.h:85
The object key class represents a JSON Object key node for use in error contexts.
Definition qx-json.h:118
The object class represents a JSON object node for use in error contexts.
Definition qx-json.h:110
The AbstractError template class completes the Error interface and acts as the base class from which ...
Definition qx-abstracterror.h:86
The JsonError class is used to report errors related to JSON manipulation.
Definition qx-json.h:155
Form
Definition qx-json.h:159
@ MissingKey
Definition qx-json.h:161
JsonError & withContext(const QxJson::ContextNode &node)
Definition qx-json.cpp:199
bool isValid() const
Definition qx-json.cpp:168
Allows QJsonParseError to be used via the Qx::Error interface.
Definition qx-json.h:590
Definition qx-json.h:316
Definition qx-json.h:312
Definition qx-json.h:321
Definition qx-json.h:294
Definition qx-json.h:307
Definition qx-json.h:325
Definition qx-json.h:299
Definition qx-json.h:280
Definition qx-json.h:285
Definition qx-json.h:290
Definition qx-json.h:277
Specifies that a type is one of several types.
Definition qx-concepts.h:513
Specifies that a type is a valid analogue for a JSON document root element.
Definition qx-json.h:585
Specifies that a type is a Qt-based associative container type.
Definition qx-concepts.h:521
Specifies that a type is a Qt-based collection type.
Definition qx-concepts.h:525
Specifies that a type is a specialization of a template.
Definition qx-concepts.h:517
The QxJson namespace encapsulates the user-extensible implementation of Qx's JSON parsing facilities.
Definition qx-json.cpp:346
Key keygen(const Value &value)=delete
The keygen template function acts as an interface through which the derivation of a key for a given t...
std::variant< File, Document, Object, ObjectKey, Array, ArrayElement > ContextNode
Definition qx-json.h:147
The Qx namespace is the main namespace through which all non-global functionality of the Qx library i...
Definition qx-processwaiter.cpp:5
QString asString(const QJsonValue &value)
Definition qx-json.cpp:320
JsonError parseJson(T &parsed, const QJsonObject &obj)
Definition qx-json.h:615
QList< QJsonValue > findAllValues(const QJsonValue &rootValue, QStringView key)
Definition qx-json.cpp:308
bool exists(const QString &fileName)
virtual QString fileName() const const override
bool open(FILE *fh, QIODeviceBase::OpenMode mode, QFileDevice::FileHandleFlags handleFlags)
virtual void close() override
QFileDevice::FileError error() const const
QString errorString() const const
bool isOpen() const const
bool isReadable() const const
QByteArray readAll()
qsizetype count() const const
QJsonArray array() const const
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
bool isArray() const const
bool isEmpty() const const
bool isObject() const const
QJsonObject object() const const
bool contains(QLatin1StringView key) const const
QJsonValue value(QLatin1StringView key) const const
QString errorString() const const
bool isArray() const const
bool isBool() const const
bool isDouble() const const
bool isObject() const const
bool isString() const const
QJsonArray toArray() const const
bool toBool(bool defaultValue) const const
double toDouble(double defaultValue) const const
QJsonObject toObject() const const
QString toString() const const
The qx-abstracterror.h header file provides access to the base class from which custom error types sh...
The qx-concepts header file provides a library of general purpose concepts as an extension of the sta...
The qx-error.h header file provides access to the Error interface.
#define QX_DECLARE_ERROR_ADAPTATION(Adaptable, Adapter)
Definition qx-error.h:132
The qx-concepts header file provides a set of various object-like and function-like macros that are d...
The Converter template struct acts as an interface that carries details on how to parse JSON to vario...
Definition qx-json.h:265
Definition qx-json.h:268
Definition qx-json.h:271
The StringLiteral template struct acts as a literal class type wrapper around a C-style string that e...
Definition qx-stringliteral.h:11