serializerbase.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. #ifndef QTJSONSERIALIZER_SERIALIZERBASE_H
  2. #define QTJSONSERIALIZER_SERIALIZERBASE_H
  3. #include "qtjsonserializer_global.h"
  4. #include "exception.h"
  5. #include "metawriters.h"
  6. #include "qtjsonserializer_helpertypes.h"
  7. #include "typeconverter.h"
  8. #include "typeextractors.h"
  9. #include <tuple>
  10. #include <optional>
  11. #include <variant>
  12. #include <QtCore/qobject.h>
  13. #include <QtCore/qmetaobject.h>
  14. #include <QtCore/qcborvalue.h>
  15. #include <QtCore/qvariant.h>
  16. #include <QtCore/qsharedpointer.h>
  17. #include <QtCore/qpointer.h>
  18. #include <QtCore/qlist.h>
  19. #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
  20. #include <QtCore/qlinkedlist.h>
  21. #endif
  22. #include <QtCore/qvector.h>
  23. #include <QtCore/qset.h>
  24. #include <QtCore/qqueue.h>
  25. #include <QtCore/qstack.h>
  26. #include <QtCore/qhash.h>
  27. #include <QtCore/qmap.h>
  28. namespace QtJsonSerializer {
  29. class SerializerBasePrivate;
  30. //! A base class for the CBOR/JSON serializers
  31. class Q_JSONSERIALIZER_EXPORT SerializerBase : public QObject, protected TypeConverter::SerializationHelper
  32. {
  33. Q_OBJECT
  34. //! Specifies whether null for value types is allowed or not
  35. Q_PROPERTY(bool allowDefaultNull READ allowDefaultNull WRITE setAllowDefaultNull NOTIFY allowDefaultNullChanged)
  36. //! Specifies whether the `objectName` property of QObjects should be serialized
  37. Q_PROPERTY(bool keepObjectName READ keepObjectName WRITE setKeepObjectName NOTIFY keepObjectNameChanged)
  38. //! Specifies whether enums should be serialized as integer or as string
  39. Q_PROPERTY(bool enumAsString READ enumAsString WRITE setEnumAsString NOTIFY enumAsStringChanged)
  40. //! Specifies whether enums should be serialized as array of integers or as string
  41. Q_PROPERTY(bool versionAsString READ versionAsString WRITE setVersionAsString NOTIFY versionAsStringChanged)
  42. //! Specifies whether datetimes should be serialized as datetime string or as unix timestamp
  43. Q_PROPERTY(bool dateAsTimeStamp READ dateAsTimeStamp WRITE setDateAsTimeStamp NOTIFY dateAsTimeStampChanged)
  44. //! Specifies whether serializing a QLocale should use the bcp47 format
  45. Q_PROPERTY(bool useBcp47Locale READ useBcp47Locale WRITE setUseBcp47Locale NOTIFY useBcp47LocaleChanged)
  46. //! Specifies how strictly the serializer should verify data when deserializing
  47. Q_PROPERTY(ValidationFlags validationFlags READ validationFlags WRITE setValidationFlags NOTIFY validationFlagsChanged)
  48. //! Specifies how the serializer should treat polymorphism for QObject classes
  49. Q_PROPERTY(Polymorphing polymorphing READ polymorphing WRITE setPolymorphing NOTIFY polymorphingChanged)
  50. //! Specifies how multi maps and sets should be serialized
  51. Q_PROPERTY(MultiMapMode multiMapMode READ multiMapMode WRITE setMultiMapMode NOTIFY multiMapModeChanged)
  52. //! Specifies whether the STORED attribute on properties has any effect
  53. Q_PROPERTY(bool ignoreStoredAttribute READ ignoresStoredAttribute WRITE setIgnoreStoredAttribute NOTIFY ignoreStoredAttributeChanged)
  54. public:
  55. //! Flags to specify how strict the serializer should validate when deserializing
  56. enum class ValidationFlag {
  57. StandardValidation = 0x00, //!< Do not perform extra validation, only make sure types are valid and compatible
  58. NoExtraProperties = 0x01, //!< Make sure the json does not contain any properties that are not in the type to deserialize it to
  59. AllProperties = 0x02, //!< Make sure all properties of the type have a value in the deserialized json data
  60. StrictBasicTypes = 0x04, //!< Make shure basic types (string, int, ...) are actually of those types, instead of accepting all that are convertible
  61. FullPropertyValidation = (NoExtraProperties | AllProperties), //!< Validate properties are exactly the same as declared
  62. FullValidation = (FullPropertyValidation | StrictBasicTypes), //!< Validate everything
  63. };
  64. Q_DECLARE_FLAGS(ValidationFlags, ValidationFlag)
  65. Q_FLAG(ValidationFlags)
  66. //! Enum to specify the modes of polymorphism
  67. enum class Polymorphing {
  68. Disabled, //!< Do not serialize polymorphic and ignore information about classes in json
  69. Enabled, //!< Use polymorphism where declared by the classes/json
  70. Forced //!< Treat every object polymorphic, and required the class information to be present in json
  71. };
  72. Q_ENUM(Polymorphing)
  73. //! Enum to specify how multi maps and sets should be serialized
  74. enum class MultiMapMode {
  75. Map, //!< Store them as json object, with each element beeing a json array containing the actual values
  76. List, //!< Store a list of pairs, where for each pair the first element is the key and the second the value
  77. DenseMap //!< Just like Map, but entries with just one value are stored as that value, instead of an array with one element
  78. };
  79. Q_ENUM(MultiMapMode)
  80. //! Registers a custom extractor for the given type
  81. template<typename TType, typename TExtractor>
  82. static void registerExtractor();
  83. //! @copybrief SerializerBase::registerExtractor
  84. static void registerExtractor(int metaTypeId, const QSharedPointer<TypeExtractor> &extractor);
  85. //! Registers a custom type for list converisons
  86. template<typename T>
  87. static inline void registerListConverters();
  88. //! Registers a custom type for set converisons
  89. template<typename T>
  90. static inline void registerSetConverters();
  91. //! Registers a custom type for map converisons
  92. template<typename TKey, typename TValue, bool mapTypes = true, bool hashTypes = true>
  93. static inline void registerMapConverters();
  94. //! Registers a custom type for QSharedPointer and QPointer converisons
  95. template<typename T>
  96. static inline void registerPointerConverters();
  97. //! Registers a custom type for list, set map and optional converisons. Also include pointer converters, if applicable
  98. template<typename T>
  99. static inline void registerBasicConverters();
  100. //! Registers two types for pair conversion
  101. template<typename T, typename U>
  102. static inline void registerPairConverters();
  103. //! Registers a number of types for std::tuple conversion
  104. template<typename... TArgs>
  105. static inline void registerTupleConverters();
  106. //! Registers a custom type for std::optional converisons
  107. template<typename T>
  108. static inline void registerOptionalConverters();
  109. //! Registers a custom type for std::variant converisons
  110. template<typename... TArgs>
  111. static inline void registerVariantConverters();
  112. //! Serializes a given variant to either CBOR or JSON, depending on the actual instance
  113. virtual std::variant<QCborValue, QJsonValue> serializeGeneric(const QVariant &value) const = 0;
  114. //! Deserializes CBOR or JSON, depending on the actual instance, to variant
  115. virtual QVariant deserializeGeneric(const std::variant<QCborValue, QJsonValue> &value, int metaTypeId, QObject *parent = nullptr) const = 0;
  116. //! @readAcFn{QJsonSerializer::allowDefaultNull}
  117. bool allowDefaultNull() const;
  118. //! @readAcFn{QJsonSerializer::keepObjectName}
  119. bool keepObjectName() const;
  120. //! @readAcFn{QJsonSerializer::enumAsString}
  121. bool enumAsString() const;
  122. //! @readAcFn{QJsonSerializer::versionAsString}
  123. bool versionAsString() const;
  124. //! @readAcFn{QJsonSerializer::dateAsTimeStamp}
  125. bool dateAsTimeStamp() const;
  126. //! @readAcFn{QJsonSerializer::useBcp47Locale}
  127. bool useBcp47Locale() const;
  128. //! @readAcFn{QJsonSerializer::validationFlags}
  129. ValidationFlags validationFlags() const;
  130. //! @readAcFn{QJsonSerializer::polymorphing}
  131. Polymorphing polymorphing() const;
  132. //! @readAcFn{QJsonSerializer::multiMapMode}
  133. MultiMapMode multiMapMode() const;
  134. //! @readAcFn{QJsonSerializer::ignoreStoredAttribute}
  135. bool ignoresStoredAttribute() const;
  136. //! Globally registers a converter factory to provide converters for all QJsonSerializer instances
  137. template <typename TConverter, int Priority = TypeConverter::Priority::Standard>
  138. static void addJsonTypeConverterFactory();
  139. //! @copybrief SerializerBase::addJsonTypeConverterFactory()
  140. static void addJsonTypeConverterFactory(TypeConverterFactory *factory);
  141. //! Adds a custom type converter to this serializer
  142. template <typename TConverter>
  143. void addJsonTypeConverter();
  144. //! @copybrief SerializerBase::addJsonTypeConverter()
  145. void addJsonTypeConverter(const QSharedPointer<TypeConverter> &converter);
  146. public Q_SLOTS:
  147. //! @writeAcFn{QJsonSerializer::allowDefaultNull}
  148. void setAllowDefaultNull(bool allowDefaultNull);
  149. //! @writeAcFn{QJsonSerializer::keepObjectName}
  150. void setKeepObjectName(bool keepObjectName);
  151. //! @writeAcFn{QJsonSerializer::enumAsString}
  152. void setEnumAsString(bool enumAsString);
  153. //! @writeAcFn{QJsonSerializer::versionAsString}
  154. void setVersionAsString(bool versionAsString);
  155. //! @writeAcFn{QJsonSerializer::dateAsTimeStamp}
  156. void setDateAsTimeStamp(bool dateAsTimeStamp);
  157. //! @writeAcFn{QJsonSerializer::useBcp47Locale}
  158. void setUseBcp47Locale(bool useBcp47Locale);
  159. //! @writeAcFn{QJsonSerializer::validationFlags}
  160. void setValidationFlags(ValidationFlags validationFlags);
  161. //! @writeAcFn{QJsonSerializer::polymorphing}
  162. void setPolymorphing(Polymorphing polymorphing);
  163. //! @writeAcFn{QJsonSerializer::multiMapMode}
  164. void setMultiMapMode(MultiMapMode multiMapMode);
  165. //! @writeAcFn{QJsonSerializer::ignoreStoredAttribute}
  166. void setIgnoreStoredAttribute(bool ignoreStoredAttribute);
  167. Q_SIGNALS:
  168. //! @notifyAcFn{QJsonSerializer::allowDefaultNull}
  169. void allowDefaultNullChanged(bool allowDefaultNull, QPrivateSignal);
  170. //! @notifyAcFn{QJsonSerializer::keepObjectName}
  171. void keepObjectNameChanged(bool keepObjectName, QPrivateSignal);
  172. //! @notifyAcFn{QJsonSerializer::enumAsString}
  173. void enumAsStringChanged(bool enumAsString, QPrivateSignal);
  174. //! @notifyAcFn{QJsonSerializer::versionAsString}
  175. void versionAsStringChanged(bool versionAsString, QPrivateSignal);
  176. //! @notifyAcFn{QJsonSerializer::dateAsTimeStamp}
  177. void dateAsTimeStampChanged(bool dateAsTimeStamp, QPrivateSignal);
  178. //! @notifyAcFn{QJsonSerializer::useBcp47Locale}
  179. void useBcp47LocaleChanged(bool useBcp47Locale, QPrivateSignal);
  180. //! @notifyAcFn{QJsonSerializer::validationFlags}
  181. void validationFlagsChanged(ValidationFlags validationFlags, QPrivateSignal);
  182. //! @notifyAcFn{QJsonSerializer::polymorphing}
  183. void polymorphingChanged(Polymorphing polymorphing, QPrivateSignal);
  184. //! @notifyAcFn{QJsonSerializer::multiMapMode}
  185. void multiMapModeChanged(MultiMapMode multiMapMode, QPrivateSignal);
  186. //! @notifyAcFn{QJsonSerializer::ignoreStoredAttribute}
  187. void ignoreStoredAttributeChanged(bool ignoreStoredAttribute, QPrivateSignal);
  188. protected:
  189. //! Default constructor
  190. explicit SerializerBase(QObject *parent = nullptr);
  191. //! @private
  192. explicit SerializerBase(SerializerBasePrivate &dd, QObject *parent);
  193. virtual QList<int> typesForTag(QCborTag tag) const = 0;
  194. // protected implementation -> internal use for the type converters
  195. QVariant getProperty(const char *name) const override;
  196. QSharedPointer<const TypeExtractor> extractor(int metaTypeId) const override;
  197. QCborValue serializeSubtype(const QMetaProperty &property, const QVariant &value) const override;
  198. QCborValue serializeSubtype(int propertyType, const QVariant &value, const QByteArray &traceHint) const override;
  199. QVariant deserializeSubtype(const QMetaProperty &property, const QCborValue &value, QObject *parent) const override;
  200. QVariant deserializeSubtype(int propertyType, const QCborValue &value, QObject *parent, const QByteArray &traceHint) const override;
  201. //! @private
  202. QCborValue serializeVariant(int propertyType, const QVariant &value) const;
  203. //! @private
  204. QVariant deserializeVariant(int propertyType, const QCborValue &value, QObject *parent, bool skipConversion = false) const;
  205. private:
  206. Q_DECLARE_PRIVATE(SerializerBase)
  207. static void registerInverseTypedefImpl(int typeId, const char *normalizedTypeName);
  208. };
  209. //! A macro the mark a class as polymorphic
  210. #define Q_JSON_POLYMORPHIC(x) \
  211. static_assert(std::is_same<decltype(x), bool>::value, "x must be bool"); \
  212. Q_CLASSINFO("polymorphic", #x)
  213. // ------------- Generic Implementation -------------
  214. template<typename TType, typename TExtractor>
  215. void SerializerBase::registerExtractor()
  216. {
  217. registerExtractor(qMetaTypeId<TType>(), QSharedPointer<TExtractor>::create());
  218. }
  219. template<typename T>
  220. void SerializerBase::registerListConverters()
  221. {
  222. MetaWriters::SequentialWriter::registerWriter<QList, T>();
  223. #if !defined(QT_NO_LINKED_LIST) && (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
  224. MetaWriters::SequentialWriter::registerWriter<QLinkedList, T>();
  225. #endif
  226. MetaWriters::SequentialWriter::registerWriter<QVector, T>();
  227. MetaWriters::SequentialWriter::registerWriter<QStack, T>();
  228. MetaWriters::SequentialWriter::registerWriter<QQueue, T>();
  229. }
  230. template<typename T>
  231. void SerializerBase::registerSetConverters()
  232. {
  233. MetaWriters::SequentialWriter::registerWriter<QSet, T>();
  234. }
  235. template<typename TKey, typename TValue, bool mapTypes, bool hashTypes>
  236. void SerializerBase::registerMapConverters()
  237. {
  238. if constexpr (mapTypes) {
  239. MetaWriters::AssociativeWriter::registerWriter<QMap, TKey, TValue>();
  240. MetaWriters::AssociativeWriter::registerWriter<QMultiMap, TKey, TValue>();
  241. }
  242. if constexpr (hashTypes) {
  243. MetaWriters::AssociativeWriter::registerWriter<QHash, TKey, TValue>();
  244. MetaWriters::AssociativeWriter::registerWriter<QMultiHash, TKey, TValue>();
  245. }
  246. }
  247. template<typename T>
  248. void SerializerBase::registerPointerConverters()
  249. {
  250. registerExtractor<QSharedPointer<T>, TypeExtractors::SmartPointerExtractor<QSharedPointer, T>>();
  251. if constexpr (std::is_base_of_v<QObject, T>)
  252. registerExtractor<QPointer<T>, TypeExtractors::SmartPointerExtractor<QPointer, T>>();
  253. }
  254. template<typename T>
  255. void SerializerBase::registerBasicConverters()
  256. {
  257. if constexpr (std::is_base_of_v<QObject, T>) {
  258. registerBasicConverters<T*>();
  259. registerPointerConverters<T>();
  260. registerBasicConverters<QSharedPointer<T>>();
  261. registerBasicConverters<QPointer<T>>();
  262. } else {
  263. registerListConverters<T>();
  264. registerSetConverters<T>();
  265. registerMapConverters<QString, T>();
  266. }
  267. }
  268. template<typename T1, typename T2>
  269. void SerializerBase::registerPairConverters()
  270. {
  271. registerExtractor<QPair<T1, T2>, TypeExtractors::PairExtractor<QPair, T1, T2>>();
  272. registerExtractor<std::pair<T1, T2>, TypeExtractors::PairExtractor<std::pair, T1, T2>>();
  273. }
  274. template<typename... TArgs>
  275. void SerializerBase::registerTupleConverters()
  276. {
  277. registerExtractor<std::tuple<TArgs...>, TypeExtractors::TupleExtractor<TArgs...>>();
  278. }
  279. template<typename T>
  280. void SerializerBase::registerOptionalConverters()
  281. {
  282. registerExtractor<std::optional<T>, TypeExtractors::OptionalExtractor<T>>();
  283. }
  284. template<typename... TArgs>
  285. void SerializerBase::registerVariantConverters()
  286. {
  287. registerExtractor<std::variant<TArgs...>, TypeExtractors::VariantExtractor<TArgs...>>();
  288. }
  289. template<typename TConverter, int Priority>
  290. void SerializerBase::addJsonTypeConverterFactory()
  291. {
  292. static_assert(std::is_base_of<TypeConverter, TConverter>::value, "T must implement QJsonTypeConverter");
  293. addJsonTypeConverterFactory(new TypeConverterStandardFactory<TConverter, Priority>{});
  294. }
  295. template<typename TConverter>
  296. void SerializerBase::addJsonTypeConverter()
  297. {
  298. static_assert(std::is_base_of<TypeConverter, TConverter>::value, "T must implement QJsonTypeConverter");
  299. addJsonTypeConverter(QSharedPointer<TConverter>::create());
  300. }
  301. }
  302. Q_DECLARE_OPERATORS_FOR_FLAGS(QtJsonSerializer::SerializerBase::ValidationFlags)
  303. Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QMultiMap)
  304. Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QMultiHash)
  305. //! @file serializerbase.h The SerializerBase header file
  306. #endif // QTJSONSERIALIZER_SERIALIZERBASE_H