5#include "qx/core/qx_core_export.h"
9#include <QJsonValueRef>
12#include <QJsonDocument>
26#define __QX_JSON_META_STRUCT_INSIDE(meta_tuple) \
27template <typename StructT> \
28 struct QxJsonMetaStructInside \
30 static inline constexpr auto memberMetadata() \
36#define __QX_JSON_META_STRUCT_OUTSIDE(self_type, meta_tuple) \
39 template <typename StructT> \
40 struct QxJsonMetaStructOutside<self_type, StructT> \
42 static inline constexpr auto memberMetadata() \
55#define QX_JSON_MEMBER(member) QxJsonPrivate::makeMemberMetadata<#member>(&StructT::member)
56#define QX_JSON_MEMBER_ALIASED(member, key) QxJsonPrivate::makeMemberMetadata<key>(&StructT::member)
58#define QX_JSON_STRUCT(...) __QX_JSON_META_STRUCT_INSIDE(std::make_tuple(QX_FOR_EACH_DELIM(QX_JSON_MEMBER, __VA_ARGS__)))
59#define QX_JSON_STRUCT_X(...) __QX_JSON_META_STRUCT_INSIDE(std::make_tuple(__VA_ARGS__))
61#define QX_JSON_STRUCT_OUTSIDE(Struct, ...) __QX_JSON_META_STRUCT_OUTSIDE(Struct, std::make_tuple(QX_FOR_EACH_DELIM(QX_JSON_MEMBER, __VA_ARGS__)))
62#define QX_JSON_STRUCT_OUTSIDE_X(Struct, ...) __QX_JSON_META_STRUCT_OUTSIDE(Struct, std::make_tuple(__VA_ARGS__))
72#define QX_JSON_MEMBER_OVERRIDE(Struct, member, ...) \
76 struct MemberOverrideCoverter<Struct, #member> \
148using ContextNode = std::variant<File, Document, Object, ObjectKey, Array, ArrayElement>;
176 {MissingKey, u
"The key does not exist."_s},
177 {TypeMismatch, u
"Value type mismatch."_s},
178 {EmptyDoc, u
"The document is empty."_s},
179 {InvalidValue, u
"Invalid value for type."_s},
180 {MissingFile, u
"File does not exist."_s},
181 {InaccessibleFile, u
"Cannot open the file."_s},
182 {FileReadError, u
"File read error."_s},
183 {FileWriteError, u
"File write error."_s}
195 JsonError(
const QString& a, Form f);
199 quint32 deriveValue()
const override;
200 QString derivePrimary()
const override;
201 QString deriveSecondary()
const override;
202 QString deriveDetails()
const override;
205 bool isValid()
const;
220template<
class Struct, Qx::StringLiteral member>
221struct MemberOverrideCoverter;
223template<
typename SelfType,
typename DelayedSelfType>
224struct QxJsonMetaStructOutside;
233 T::template QxJsonMetaStructInside<T>::memberMetadata();
238 QxJsonMetaStructOutside<T, T>::memberMetadata();
247 { Converter<T>::fromJson(tValue,
QJsonValue()) } -> std::same_as<Qx::JsonError>;
248 { Converter<T>::toJson(tValue) } ->
qjson_type;
251template<
class K,
typename T, Qx::StringLiteral N>
252concept json_override_convertible =
requires(T& tValue) {
253 { MemberOverrideCoverter<K, N>::fromJson(tValue,
QJsonValue()) } -> std::same_as<Qx::JsonError>;
254 { MemberOverrideCoverter<K, N>::toJson(tValue) } -> qjson_type;
257template<
typename Key,
class Value>
260template<
typename Key,
class Value>
262 { keygen<Key, Value>(v) } -> std::same_as<Key>;
285namespace QxJsonPrivate
288static inline const QString ERR_CONV_TYPE = u
"JSON Error: Converting value to %1"_s;
289static inline const QString ERR_NO_KEY = u
"JSON Error: Could not retrieve key '%1'."_s;
290static inline const QString ERR_PARSE_DOC = u
"JSON Error: Could not parse JSON document."_s;
291static inline const QString ERR_READ_FILE = u
"JSON Error: Could not read JSON file."_s;
292static inline const QString ERR_WRITE_FILE = u
"JSON Error: Could not write JSON file."_s;
295template<Qx::StringLiteral MemberN,
typename MemberT,
class Struct>
299 typedef MemberT M_TYPE;
300 MemberT Struct::* mPtr;
304template <Qx::StringLiteral N,
typename T,
class S>
305constexpr MemberMetadata<N, T, S> makeMemberMetadata(T S::*memberPtr)
310template<
typename T> [[maybe_unused]]
static inline QString typeString() =
delete;
311template<
typename T> [[maybe_unused]]
static inline bool isType(
const QJsonValue& v) =
delete;
312template<
typename T> [[maybe_unused]]
static inline T toType(
const QJsonValue& v) =
delete;
314template<>
inline QString typeString<bool>() {
return u
"bool"_s; };
315template<>
inline QString typeString<double>() {
return u
"double"_s; };
316template<>
inline QString typeString<QString>() {
return u
"string"_s; };
317template<>
inline QString typeString<QJsonArray>() {
return u
"array"_s; };
318template<>
inline QString typeString<QJsonObject>() {
return u
"object"_s; };
320template<>
inline bool isType<bool>(
const QJsonValue& v) {
return v.
isBool(); };
323template<>
inline bool isType<QJsonArray>(
const QJsonValue& v) {
return v.
isArray(); };
324template<>
inline bool isType<QJsonObject>(
const QJsonValue& v) {
return v.
isObject(); };
326template<>
inline bool toType<bool>(
const QJsonValue& v) {
return v.
toBool(); };
354constexpr auto getMemberMeta()
356 return K::template QxJsonMetaStructInside<K>::memberMetadata();
361constexpr auto getMemberMeta()
363 return QxJson::QxJsonMetaStructOutside<K, K>::memberMetadata();
366template<
class K,
typename T, Qx::StringLiteral N>
367 requires QxJson::json_override_convertible<K, T, N>
370 return QxJson::MemberOverrideCoverter<K, N>::fromJson(value, jv);
373template<
class K,
typename T, Qx::StringLiteral N>
374 requires QxJson::json_override_convertible<K, T, N>
375auto overrideSerialize(
const T& value)
377 return QxJson::MemberOverrideCoverter<K, N>::toJson(value);
389auto standardSerialize(
const T& value)
403 requires qjson_type<T>
408 if(!QxJsonPrivate::isType<T>(jValue))
411 value = QxJsonPrivate::toType<T>(jValue);
415 static T toJson(
const T& value)
427 requires json_struct<T>
443 constexpr auto memberMetas = QxJsonPrivate::getMemberMeta<T>();
449 std::apply([&](
auto&&... memberMeta)
constexpr {
453 static constexpr auto mName = std::remove_reference<
decltype(memberMeta)>::type::M_NAME;
455 using mType =
typename std::remove_reference<
decltype(memberMeta)>::type::M_TYPE;
456 auto& mRef = value.*(memberMeta.mPtr);
461 if constexpr(json_optional<mType>)
476 if constexpr(json_override_convertible<T, mType, mName>)
477 cnvError = QxJsonPrivate::overrideParse<T, mType, mName>(mRef, mValue);
479 cnvError = QxJsonPrivate::standardParse<mType>(mRef, mValue);
495 constexpr auto memberMetas = QxJsonPrivate::getMemberMeta<T>();
498 std::apply([&](
auto&&... memberMeta)
constexpr {
502 static constexpr auto mName = std::remove_reference<
decltype(memberMeta)>::type::M_NAME;
504 using mType =
typename std::remove_reference<
decltype(memberMeta)>::type::M_TYPE;
505 auto& mRef = value.*(memberMeta.mPtr);
508 if constexpr(json_optional<mType>)
515 if constexpr(json_override_convertible<T, mType, mName>)
516 jObject.
insert(mKey, QxJsonPrivate::overrideSerialize<T, mType, mName>(mRef));
518 jObject.
insert(mKey, QxJsonPrivate::standardSerialize<mType>(mRef));
527 requires json_collective<T>
530 using E =
typename T::value_type;
550 for(
auto i = 0; i < jArray.
count(); ++i)
553 if(cnvError = Converter<E>::fromJson(converted, jArray[i]); cnvError.
isValid())
571 for(
const E& e : value)
574 if constexpr(json_optional<E>)
580 jArray.
append(Converter<E>::toJson(e));
588 requires json_associative<T>
591 using K =
typename T::key_type;
592 using V =
typename T::mapped_type;
611 for(
auto i = 0; i < jArray.
count(); ++i)
614 if(cnvError = Converter<V>::fromJson(converted, jArray[i]); cnvError.
isValid())
620 value.insert(keygen<K, V>(converted), converted);
632 for(
const V& v : value)
635 if constexpr(json_optional<V>)
641 jArray.
append(Converter<V>::toJson(v));
649 requires json_optional<T>
652 using O =
typename T::value_type;
660 value = std::move(opt);
665 static auto toJson(
const T& value)
668 return Converter<O>::toJson(*value);
673 requires std::integral<T> && (!std::same_as<T, bool>)
681 value =
static_cast<T
>(jValue.
toDouble());
685 static double toJson(
const T& value)
687 return static_cast<double>(value);
707 static inline const QString OFFSET_STR = u
"Position: %1."_s;
721 quint32 deriveValue()
const override;
722 QString derivePrimary()
const override;
723 QString deriveSecondary()
const override;
762 requires json_root<T>
785 requires json_root<T>
792 requires json_root<T>
810 if(jsonData.isEmpty())
830 requires json_root<T>
852 if(serialized.
write(jsonData) != jsonData.
size())
859 requires json_root<T>
862 QFile file(filePath);
868 requires json_root<T>
871 QFile file(serializedPath);
The array element key class represents a JSON Array element node for use in error contexts.
Definition qx-json.h:138
The array class represents a JSON array node for use in error contexts.
Definition qx-json.h:130
The document class represents a JSON document node for use in error contexts.
Definition qx-json.h:100
The file class represents a JSON file node for use in error contexts.
Definition qx-json.h:86
The object key class represents a JSON Object key node for use in error contexts.
Definition qx-json.h:119
The object class represents a JSON object node for use in error contexts.
Definition qx-json.h:111
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:156
Form
Definition qx-json.h:160
@ EmptyDoc
Definition qx-json.h:164
@ InaccessibleFile
Definition qx-json.h:167
@ InvalidValue
Definition qx-json.h:165
@ FileReadError
Definition qx-json.h:168
@ TypeMismatch
Definition qx-json.h:163
@ MissingKey
Definition qx-json.h:162
@ FileWriteError
Definition qx-json.h:169
@ MissingFile
Definition qx-json.h:166
JsonError & withContext(const QxJson::ContextNode &node)
Definition qx-json.cpp:220
bool isValid() const
Definition qx-json.cpp:189
Allows QJsonParseError to be used via the Qx::Error interface.
Definition qx-json.h:704
Specifies that a type is an associative container, the value type of which is convertible,...
Definition qx-json.h:270
Specifies that a type is a non-associative container, the value type of which is convertible to/from ...
Definition qx-json.h:266
Specifies that a type is a container, and abides by the other corresponding restrictions for that kin...
Definition qx-json.h:275
Specifies that a type is generally convertible to/from JSON.
Definition qx-json.h:246
Specifies that a type has a known method for creating a corresponding key.
Definition qx-json.h:261
Specifies that a type is a specialization of std::optional that manages values of a JSON convertible ...
Definition qx-json.h:279
Specifies that a type is a JSON-tied struct registered with QX_JSON_STRUCT().
Definition qx-json.h:232
Specifies that a type is a JSON-tied struct registered with QX_JSON_STRUCT_OUTSIDE().
Definition qx-json.h:237
Specifies that a type is a JSON-tied struct.
Definition qx-json.h:242
Specifies that a type is one of the fundamental JSON types within Qt's JSON system.
Definition qx-json.h:229
Specifies that a type is one of several types.
Definition qx-concepts.h:502
Specifies that a type is a valid analogue for a JSON document root element.
Definition qx-json.h:699
Specifies that a type is a Qt-based associative container type.
Definition qx-concepts.h:510
Specifies that a type is a Qt-based collection type.
Definition qx-concepts.h:514
Specifies that a type is a specialization of a template.
Definition qx-concepts.h:506
The QxJson namespace encapsulates the user-extensible implementation of Qx's JSON parsing facilities.
Definition qx-json.cpp:418
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:148
The Qx namespace is the main namespace through which all non-global functionality of the Qx library i...
Definition qx-abstracterror.cpp:13
void serializeJson(QJsonObject &serialized, const T &struc)
Definition qx-json.h:739
QString asString(const QJsonValue &value)
Definition qx-json.cpp:392
JsonError parseJson(T &parsed, const QJsonObject &obj)
Definition qx-json.h:729
QList< QJsonValue > findAllValues(const QJsonValue &rootValue, QStringView key)
Definition qx-json.cpp:380
bool isEmpty() const const
qsizetype size() const const
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
qint64 write(const QByteArray &data)
void append(const QJsonValue &value)
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
QJsonObject::iterator insert(QLatin1StringView key, const QJsonValue &value)
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/serialize JSO...
Definition qx-json.h:218
The StringLiteral template struct acts as a literal class type wrapper around a C-style string that e...
Definition qx-stringliteral.h:11