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>;
175 {MissingKey, u
"The key does not exist."_s},
176 {TypeMismatch, u
"Value type mismatch."_s},
177 {EmptyDoc, u
"The document is empty."_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 {FileWriteError, u
"File write error."_s}
193 JsonError(
const QString& a, Form f);
197 quint32 deriveValue()
const override;
198 QString derivePrimary()
const override;
199 QString deriveSecondary()
const override;
200 QString deriveDetails()
const override;
203 bool isValid()
const;
213namespace QxJsonPrivate
216static inline const QString ERR_CONV_TYPE = u
"JSON Error: Converting value to %1"_s;
217static inline const QString ERR_NO_KEY = u
"JSON Error: Could not retrieve key '%1'."_s;
218static inline const QString ERR_PARSE_DOC = u
"JSON Error: Could not parse JSON document."_s;
219static inline const QString ERR_READ_FILE = u
"JSON Error: Could not read JSON file."_s;
220static inline const QString ERR_WRITE_FILE = u
"JSON Error: Could not write JSON file."_s;
223template<Qx::StringLiteral MemberN,
typename MemberT,
class Struct>
227 typedef MemberT M_TYPE;
228 MemberT Struct::* mPtr;
232template <Qx::StringLiteral N,
typename T,
class S>
233constexpr MemberMetadata<N, T, S> makeMemberMetadata(T S::*memberPtr)
238template<
typename T> [[maybe_unused]]
static inline QString typeString() =
delete;
239template<
typename T> [[maybe_unused]]
static inline bool isType(
const QJsonValue& v) =
delete;
240template<
typename T> [[maybe_unused]]
static inline T toType(
const QJsonValue& v) =
delete;
242template<>
inline QString typeString<bool>() {
return u
"bool"_s; };
243template<>
inline QString typeString<double>() {
return u
"double"_s; };
244template<>
inline QString typeString<QString>() {
return u
"string"_s; };
245template<>
inline QString typeString<QJsonArray>() {
return u
"array"_s; };
246template<>
inline QString typeString<QJsonObject>() {
return u
"object"_s; };
248template<>
inline bool isType<bool>(
const QJsonValue& v) {
return v.
isBool(); };
251template<>
inline bool isType<QJsonArray>(
const QJsonValue& v) {
return v.
isArray(); };
252template<>
inline bool isType<QJsonObject>(
const QJsonValue& v) {
return v.
isObject(); };
254template<>
inline bool toType<bool>(
const QJsonValue& v) {
return v.
toBool(); };
269template<
class Struct, Qx::StringLiteral member>
272template<
typename SelfType,
typename DelayedSelfType>
282 T::template QxJsonMetaStructInside<T>::memberMetadata();
287 QxJsonMetaStructOutside<T, T>::memberMetadata();
296 { Converter<T>::fromJson(tValue,
QJsonValue()) } -> std::same_as<Qx::JsonError>;
297 { Converter<T>::toJson(tValue) } ->
qjson_type;
300template<
class K,
typename T, Qx::StringLiteral N>
302 { MemberOverrideCoverter<K, N>::fromJson(tValue,
QJsonValue()) } -> std::same_as<Qx::JsonError>;
303 { MemberOverrideCoverter<K, N>::toJson(tValue) } ->
qjson_type;
306template<
typename Key,
class Value>
309template<
typename Key,
class Value>
311 { keygen<Key, Value>(v) } -> std::same_as<Key>;
334namespace QxJsonPrivate
358constexpr auto getMemberMeta()
360 return K::template QxJsonMetaStructInside<K>::memberMetadata();
365constexpr auto getMemberMeta()
370template<
class K,
typename T, Qx::StringLiteral N>
377template<
class K,
typename T, Qx::StringLiteral N>
379auto overrideSerialize(
const T& value)
393auto standardSerialize(
const T& value)
407 requires qjson_type<T>
412 if(!QxJsonPrivate::isType<T>(jValue))
415 value = QxJsonPrivate::toType<T>(jValue);
419 static T toJson(
const T& value)
431 requires json_struct<T>
447 constexpr auto memberMetas = QxJsonPrivate::getMemberMeta<T>();
453 std::apply([&](
auto&&... memberMeta)
constexpr {
457 static constexpr auto mName = std::remove_reference<
decltype(memberMeta)>::type::M_NAME;
459 using mType =
typename std::remove_reference<
decltype(memberMeta)>::type::M_TYPE;
460 auto& mRef = value.*(memberMeta.mPtr);
465 if constexpr(json_optional<mType>)
480 if constexpr(json_override_convertible<T, mType, mName>)
481 cnvError = QxJsonPrivate::overrideParse<T, mType, mName>(mRef, mValue);
483 cnvError = QxJsonPrivate::standardParse<mType>(mRef, mValue);
499 constexpr auto memberMetas = QxJsonPrivate::getMemberMeta<T>();
502 std::apply([&](
auto&&... memberMeta)
constexpr {
506 static constexpr auto mName = std::remove_reference<
decltype(memberMeta)>::type::M_NAME;
508 using mType =
typename std::remove_reference<
decltype(memberMeta)>::type::M_TYPE;
509 auto& mRef = value.*(memberMeta.mPtr);
512 if constexpr(json_optional<mType>)
519 if constexpr(json_override_convertible<T, mType, mName>)
520 jObject.
insert(mKey, QxJsonPrivate::overrideSerialize<T, mType, mName>(mRef));
522 jObject.
insert(mKey, QxJsonPrivate::standardSerialize<mType>(mRef));
531 requires json_collective<T>
534 using E =
typename T::value_type;
554 for(
auto i = 0; i < jArray.
count(); ++i)
557 if(cnvError = Converter<E>::fromJson(converted, jArray[i]); cnvError.
isValid())
575 for(
const E& e : value)
578 if constexpr(json_optional<E>)
584 jArray.
append(Converter<E>::toJson(e));
592 requires json_associative<T>
595 using K =
typename T::key_type;
596 using V =
typename T::mapped_type;
615 for(
auto i = 0; i < jArray.
count(); ++i)
618 if(cnvError = Converter<V>::fromJson(converted, jArray[i]); cnvError.
isValid())
624 value.insert(keygen<K, V>(converted), converted);
636 for(
const V& v : value)
639 if constexpr(json_optional<V>)
645 jArray.
append(Converter<V>::toJson(v));
653 requires json_optional<T>
656 using O =
typename T::value_type;
664 value = std::move(opt);
669 static auto toJson(
const T& value)
672 return Converter<O>::toJson(*value);
677 requires std::integral<T> && (!std::same_as<T, bool>)
685 value =
static_cast<T
>(jValue.
toDouble());
689 static double toJson(
const T& value)
691 return static_cast<double>(value);
711 static inline const QString OFFSET_STR = u
"Position: %1."_s;
725 quint32 deriveValue()
const override;
726 QString derivePrimary()
const override;
727 QString deriveSecondary()
const override;
766 requires json_root<T>
789 requires json_root<T>
796 requires json_root<T>
814 if(jsonData.isEmpty())
834 requires json_root<T>
856 if(serialized.
write(jsonData) != jsonData.
size())
863 requires json_root<T>
866 QFile file(filePath);
872 requires json_root<T>
875 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:166
@ FileReadError
Definition qx-json.h:167
@ TypeMismatch
Definition qx-json.h:163
@ MissingKey
Definition qx-json.h:162
@ FileWriteError
Definition qx-json.h:168
@ MissingFile
Definition qx-json.h:165
JsonError & withContext(const QxJson::ContextNode &node)
Definition qx-json.cpp:227
bool isValid() const
Definition qx-json.cpp:196
Allows QJsonParseError to be used via the Qx::Error interface.
Definition qx-json.h:708
Specifies that a type is an associative container, the value type of which is convertible,...
Definition qx-json.h:319
Specifies that a type is a non-associative container, the value type of which is convertible to/from ...
Definition qx-json.h:315
Specifies that a type is a container, and abides by the other corresponding restrictions for that kin...
Definition qx-json.h:324
Specifies that a type is generally convertible to/from JSON.
Definition qx-json.h:295
Specifies that a type has a known method for creating a corresponding key.
Definition qx-json.h:310
Specifies that a type is a specialization of std::optional that manages values of a JSON convertible ...
Definition qx-json.h:328
Specifies that a type is a JSON-tied struct registered with QX_JSON_STRUCT().
Definition qx-json.h:281
Specifies that a type is a JSON-tied struct registered with QX_JSON_STRUCT_OUTSIDE().
Definition qx-json.h:286
Specifies that a type is a JSON-tied struct.
Definition qx-json.h:291
Specifies that a type is one of the fundamental JSON types within Qt's JSON system.
Definition qx-json.h:278
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:703
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:425
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-processwaiter.cpp:5
void serializeJson(QJsonObject &serialized, const T &struc)
Definition qx-json.h:743
QString asString(const QJsonValue &value)
Definition qx-json.cpp:399
JsonError parseJson(T &parsed, const QJsonObject &obj)
Definition qx-json.h:733
QList< QJsonValue > findAllValues(const QJsonValue &rootValue, QStringView key)
Definition qx-json.cpp:387
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:267
The StringLiteral template struct acts as a literal class type wrapper around a C-style string that e...
Definition qx-stringliteral.h:11