5#include "qx/core/qx_core_export.h"
9#include <QJsonValueRef>
12#include <QJsonDocument>
29#define __QX_JSON_META_STRUCT_INSIDE(meta_tuple) \
30 template <typename StructT> \
31 struct QxJsonMetaStructInside \
33 static inline constexpr auto memberMetadata() \
39#define __QX_JSON_META_STRUCT_OUTSIDE(self_type, meta_tuple) \
42 template <typename StructT> \
43 struct QxJsonMetaStructOutside<self_type, StructT> \
45 static inline constexpr auto memberMetadata() \
54#define QX_JSON_MEMBER(member) QxJsonPrivate::makeMemberMetadata<#member>(&StructT::member)
55#define QX_JSON_MEMBER_ALIASED(member, key) QxJsonPrivate::makeMemberMetadata<key>(&StructT::member)
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__))
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__))
71#define QX_JSON_MEMBER_OVERRIDE(Struct, member, ...) \
75 struct MemberOverrideCoverter<Struct, #member> \
147using ContextNode = std::variant<File, Document, Object, ObjectKey, Array, ArrayElement>;
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}
192 JsonError(
const QString& a, Form f);
196 quint32 deriveValue()
const override;
197 QString derivePrimary()
const override;
198 QString deriveSecondary()
const override;
199 QString deriveDetails()
const override;
202 bool isValid()
const;
212namespace QxJsonPrivate
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;
221template<Qx::StringLiteral MemberN,
typename MemberT,
class Struct>
225 typedef MemberT M_TYPE;
226 MemberT Struct::* mPtr;
230template <Qx::StringLiteral N,
typename T,
class S>
231constexpr MemberMetadata<N, T, S> makeMemberMetadata(T S::*memberPtr)
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;
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; };
246template<>
inline bool isType<bool>(
const QJsonValue& v) {
return v.
isBool(); };
249template<>
inline bool isType<QJsonArray>(
const QJsonValue& v) {
return v.
isArray(); };
250template<>
inline bool isType<QJsonObject>(
const QJsonValue& v) {
return v.
isObject(); };
252template<>
inline bool toType<bool>(
const QJsonValue& v) {
return v.
toBool(); };
267template<
class Struct, Qx::StringLiteral member>
270template<
typename SelfType,
typename DelayedSelfType>
281 T::template QxJsonMetaStructInside<T>::memberMetadata();
286 QxJsonMetaStructOutside<T, T>::memberMetadata();
295 { Converter<T>::fromJson(tValue,
QJsonValue()) } -> std::same_as<Qx::JsonError>;
298template<
class K,
typename T, Qx::StringLiteral N>
300 { MemberOverrideCoverter<K, N>::fromJson(tValue,
QJsonValue()) } -> std::same_as<Qx::JsonError>;
303template<
typename Key,
class Value>
306template<
typename Key,
class Value>
308 { keygen<Key, Value>(v) } -> std::same_as<Key>;
331namespace QxJsonPrivate
353constexpr auto getMemberMeta()
355 return K::template QxJsonMetaStructInside<K>::memberMetadata();
360constexpr auto getMemberMeta()
365template<
class K,
typename T, Qx::StringLiteral N>
388 requires qjson_type<T>
393 if(!QxJsonPrivate::isType<T>(jValue))
394 return Qx::JsonError(QxJsonPrivate::ERR_CONV_TYPE.arg(QxJsonPrivate::typeString<T>()), Qx::JsonError::TypeMismatch);
396 value = QxJsonPrivate::toType<T>(jValue);
402 requires json_struct<T>
408 return Qx::JsonError(QxJsonPrivate::ERR_CONV_TYPE.arg(QxJsonPrivate::typeString<QJsonObject>()), Qx::JsonError::TypeMismatch)
418 constexpr auto memberMetas = QxJsonPrivate::getMemberMeta<T>();
424 std::apply([&](
auto&&... memberMeta)
constexpr {
428 static constexpr auto mName = std::remove_reference<
decltype(memberMeta)>::type::M_NAME;
430 using mType =
typename std::remove_reference<
decltype(memberMeta)>::type::M_TYPE;
431 auto mPtr = memberMeta.mPtr;
436 if constexpr(json_optional<mType>)
438 value.*mPtr = std::nullopt;
451 if constexpr(json_override_convertible<T, mType, mName>)
452 cnvError = QxJsonPrivate::performOverrideConversion<T, mType, mName>(value.*mPtr, mValue);
454 cnvError = QxJsonPrivate::performRegularConversion<mType>(value.*mPtr, mValue);
466 requires json_collective<T>
469 using E =
typename T::value_type;
478 return Qx::JsonError(QxJsonPrivate::ERR_CONV_TYPE.arg(QxJsonPrivate::typeString<QJsonArray>()), Qx::JsonError::TypeMismatch)
489 for(
auto i = 0; i < jArray.
count(); ++i)
492 if(cnvError = Converter<E>::fromJson(converted, jArray[i]); cnvError.
isValid())
506 requires json_associative<T>
511 using K =
typename T::key_type;
512 using V =
typename T::mapped_type;
519 return Qx::JsonError(QxJsonPrivate::ERR_CONV_TYPE.arg(QxJsonPrivate::typeString<QJsonArray>()), Qx::JsonError::TypeMismatch)
529 for(
auto i = 0; i < jArray.
count(); ++i)
532 if(cnvError = Converter<V>::fromJson(converted, jArray[i]); cnvError.
isValid())
538 value.insert(keygen<K, V>(converted), converted);
546 requires json_optional<T>
549 using O =
typename T::value_type;
557 value = std::move(opt);
564 requires std::integral<T> && (!std::same_as<T, bool>)
570 return Qx::JsonError(QxJsonPrivate::ERR_CONV_TYPE.arg(QxJsonPrivate::typeString<double>()), Qx::JsonError::TypeMismatch);
572 value =
static_cast<T
>(jValue.
toDouble());
593 static inline const QString OFFSET_STR = u
"Position: %1."_s;
607 quint32 deriveValue()
const override;
608 QString derivePrimary()
const override;
609 QString deriveSecondary()
const override;
634 requires json_root<T>
657 requires json_root<T>
678 if(jsonData.isEmpty())
698 requires json_root<T>
701 QFile file(filePath);
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
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
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
The StringLiteral template struct acts as a literal class type wrapper around a C-style string that e...
Definition qx-stringliteral.h:11