| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- #ifndef QTJSONSERIALIZER_TYPECONVERTER_H
- #define QTJSONSERIALIZER_TYPECONVERTER_H
- #include "qtjsonserializer_global.h"
- #include <type_traits>
- #include <limits>
- #include <QtCore/qmetatype.h>
- #include <QtCore/qmetaobject.h>
- #include <QtCore/qjsonvalue.h>
- #include <QtCore/qcborvalue.h>
- #include <QtCore/qvariant.h>
- #include <QtCore/qsharedpointer.h>
- namespace QtJsonSerializer {
- //! Interface to extract data from any generic container
- class Q_JSONSERIALIZER_EXPORT TypeExtractor
- {
- Q_DISABLE_COPY(TypeExtractor)
- public:
- TypeExtractor();
- virtual ~TypeExtractor();
- //! Returns the identifier of the general type this extractor is for
- virtual QByteArray baseType() const = 0;
- //! Returns an ordered list of subtypes found in types handled by this extractor
- virtual QList<int> subtypes() const = 0;
- //! Extracts the data of a value of the extractors type at the given index
- virtual QVariant extract(const QVariant &value, int index = -1) const = 0;
- //! Emplaces the value into the target of the extractors type at the given index
- virtual void emplace(QVariant &target, const QVariant &value, int index = -1) const = 0;
- };
- class TypeConverterPrivate;
- //! An interface to create custom serializer type converters
- class Q_JSONSERIALIZER_EXPORT TypeConverter
- {
- Q_DISABLE_COPY(TypeConverter)
- public:
- //! A placeholder tag to be used if no tag is expected/allowed/given
- static constexpr auto NoTag = static_cast<QCborTag>(std::numeric_limits<std::underlying_type_t<QCborTag>>::max());
- //! Sample values for a priority value (default converters are mostly Standard and are guaranteed to be between Low and High)
- enum Priority : int {
- ExtremlyLow = -0x00FFFFFF,
- VeryLow = -0x0000FFFF,
- Low = -0x000000FF,
- Standard = 0x00000000,
- High = 0x000000FF,
- VeryHigh = 0x0000FFFF,
- ExtremlyHigh = 0x00FFFFFF
- };
- //! The possible results of canDeserialize(), used internally only
- enum DeserializationCapabilityResult : int {
- Positive = 1, //!< The converter can deserialize the given data
- Guessed = 2, //!< The converter guessed a type for the given data
- Negative = -1, //!< The converter cannot deserialize the given data
- WrongTag = -2 //!< The converter could deserialize the given data, but the tag does not match
- };
- //! Helper class passed to the type converter by the serializer. Do not implement yourself
- class Q_JSONSERIALIZER_EXPORT SerializationHelper
- {
- Q_DISABLE_COPY(SerializationHelper)
- public:
- SerializationHelper();
- virtual ~SerializationHelper();
- //! Returns true, if de/serializing to JSON, and false for CBOR
- virtual bool jsonMode() const = 0;
- //! Returns a property from the serializer
- virtual QVariant getProperty(const char *name) const = 0;
- //! Returns a tag registered for the given metaTypeId
- virtual QCborTag typeTag(int metaTypeId) const = 0;
- //! Returns a reference to an extractor for the given type, or nullptr
- virtual QSharedPointer<const TypeExtractor> extractor(int metaTypeId) const = 0;
- //! Serialize a subvalue, represented by a meta property
- virtual QCborValue serializeSubtype(const QMetaProperty &property, const QVariant &value) const = 0;
- //! Serialize a subvalue, represented by a type id
- virtual QCborValue serializeSubtype(int propertyType, const QVariant &value, const QByteArray &traceHint = {}) const = 0;
- //! Deserialize a subvalue, represented by a meta property
- virtual QVariant deserializeSubtype(const QMetaProperty &property, const QCborValue &value, QObject *parent) const = 0;
- //! Deserialize a subvalue, represented by a type id
- virtual QVariant deserializeSubtype(int propertyType, const QCborValue &value, QObject *parent, const QByteArray &traceHint = {}) const = 0;
- };
- //! Constructor
- TypeConverter();
- //! Destructor
- virtual ~TypeConverter();
- //! The name of the converter. Used for debugging purpose
- virtual QByteArray name() const = 0;
- //! Returns the priority of this converter
- int priority() const;
- //! Sets the priority of this converter
- void setPriority(int priority);
- //! Returns the helper associated with this converter
- const SerializationHelper *helper() const;
- //! @private
- void setHelper(const SerializationHelper *helper);
- //! Returns true, if this implementation can convert the given type
- virtual bool canConvert(int metaTypeId) const = 0;
- //! Returns a list of allowed tags for the given type
- virtual QList<QCborTag> allowedCborTags(int metaTypeId) const;
- //! Returns a list of allowed types for the given type and tag
- virtual QList<QCborValue::Type> allowedCborTypes(int metaTypeId, QCborTag tag) const = 0;
- //! Returns a type guessed from the tag and data, that is supported by the converter
- virtual int guessType(QCborTag tag, QCborValue::Type dataType) const;
- //! @private
- DeserializationCapabilityResult canDeserialize(int &metaTypeId,
- QCborTag tag,
- QCborValue::Type dataType) const;
- //! Called by the serializer to serializer your given type to CBOR
- virtual QCborValue serialize(int propertyType, const QVariant &value) const = 0;
- //! Called by the serializer to deserializer your given type from CBOR
- virtual QVariant deserializeCbor(int propertyType, const QCborValue &value, QObject *parent) const = 0;
- //! Called by the serializer to deserializer your given type from JSON
- virtual QVariant deserializeJson(int propertyType, const QCborValue &value, QObject *parent) const;
- private:
- QScopedPointer<TypeConverterPrivate> d;
- void mapTypesToJson(QList<QCborValue::Type> &typeList) const;
- };
- //! Macro to implement the TypeConverter::name method in a subclass
- #define QT_JSONSERIALIZER_TYPECONVERTER_NAME(className) inline QByteArray name() const override { \
- static_assert(std::is_same_v<className, std::decay_t<decltype(*this)>>); \
- return QByteArrayLiteral(#className); \
- }
- //! A factory interface to create instances of QJsonTypeConverters
- class Q_JSONSERIALIZER_EXPORT TypeConverterFactory
- {
- Q_DISABLE_COPY(TypeConverterFactory)
- public:
- TypeConverterFactory();
- virtual ~TypeConverterFactory();
- //! The primary factory method to create converters
- virtual QSharedPointer<TypeConverter> createConverter() const = 0;
- };
- //! A template implementation of TypeConverterFactory to generically create simply converters
- template <typename TConverter, int OverwritePriority = TypeConverter::Priority::Standard>
- class TypeConverterStandardFactory : public TypeConverterFactory
- {
- public:
- QSharedPointer<TypeConverter> createConverter() const override;
- };
- // ------------- GENERIC IMPLEMENTATION -------------
- template<typename TConverter, int OverwritePriority>
- QSharedPointer<TypeConverter> TypeConverterStandardFactory<TConverter, OverwritePriority>::createConverter() const
- {
- auto converter = QSharedPointer<TConverter>::create();
- if (OverwritePriority != TypeConverter::Priority::Standard)
- converter->setPriority(OverwritePriority);
- return converter;
- }
- }
- #endif // QTJSONSERIALIZER_TYPECONVERTER_H
|