An interface to create custom serializer type converters. More...
#include <typeconverter.h>
Classes | |
class | SerializationHelper |
Helper class passed to the type converter by the serializer. Do not implement yourself. More... | |
Public Types | |
enum | Priority : int { ExtremlyLow = -0x00FFFFFF, VeryLow = -0x0000FFFF, Low = -0x000000FF, Standard = 0x00000000, High = 0x000000FF, VeryHigh = 0x0000FFFF, ExtremlyHigh = 0x00FFFFFF } |
Sample values for a priority value (default converters are mostly Standard and are guaranteed to be between Low and High) | |
enum | DeserializationCapabilityResult : int { Positive = 1, Guessed = 2, Negative = -1, WrongTag = -2 } |
The possible results of canDeserialize(), used internally only. More... | |
Public Member Functions | |
TypeConverter () | |
Constructor. | |
virtual | ~TypeConverter () |
Destructor. | |
virtual QByteArray | name () const =0 |
The name of the converter. Used for debugging purpose. | |
int | priority () const |
Returns the priority of this converter. More... | |
void | setPriority (int priority) |
Sets the priority of this converter. More... | |
const SerializationHelper * | helper () const |
Returns the helper associated with this converter. More... | |
virtual bool | canConvert (int metaTypeId) const =0 |
Returns true, if this implementation can convert the given type. More... | |
virtual QList< QCborTag > | allowedCborTags (int metaTypeId) const |
Returns a list of allowed tags for the given type. More... | |
virtual QList< QCborValue::Type > | allowedCborTypes (int metaTypeId, QCborTag tag) const =0 |
Returns a list of allowed types for the given type and tag. More... | |
virtual int | guessType (QCborTag tag, QCborValue::Type dataType) const |
Returns a type guessed from the tag and data, that is supported by the converter. More... | |
virtual QCborValue | serialize (int propertyType, const QVariant &value) const =0 |
Called by the serializer to serializer your given type to CBOR. More... | |
virtual QVariant | deserializeCbor (int propertyType, const QCborValue &value, QObject *parent) const =0 |
Called by the serializer to deserializer your given type from CBOR. More... | |
virtual QVariant | deserializeJson (int propertyType, const QCborValue &value, QObject *parent) const |
Called by the serializer to deserializer your given type from JSON. More... | |
Static Public Attributes | |
static constexpr auto | NoTag = static_cast<QCborTag>(std::numeric_limits<std::underlying_type_t<QCborTag>>::max()) |
A placeholder tag to be used if no tag is expected/allowed/given. | |
An interface to create custom serializer type converters.
If you have a custom class, that cannot be serialized with the converters the library has built in, you will need to create a custom type converter in order to handle your type. Implement this interface for your custom type, and add it to a serializer instance by calling SerializerBase::addJsonTypeConverter.
To understand how it works, here is a small example for a custom type converter. First, the definition of the custom class.
This class is neither a gadget nor an object, and thus be default not serializable. For this example, we want to get the following json out of the serializer for this type:
In case of a CBOR serialization, it should be equivalent, but tagged with our custom CBOR tag:
To do this, we implement our custom type converter:
There are 4 required methods to be implemented. In addition to that, there is also the TypeConverter::priority. It is not relevant for this example, but might be for your special case. For certain use cases, some of the three optional methods may also be required
This method is called be the serializer to determine whether your converter can handle a specific type or not. In our case, all that needs to be done is to check if the passed type is our Foo type:
This method is called be the serializer to determine which cbor or types your converter can deserialize. For the example, we serialize to a json object (or cbor map), and thus can only deserialize objects/maps as well.
As you can see, we only need to provide the CBOR type. The json type is autmatically derived from the CBOR type, according to the CBOR specification.
This method contains the actual code to convert our c++ Foo object into a CBOR value. As CBOR can be converter to JSON automatically, and to ensure compability between the CBOR and JSON representation of data, only a conversion to CBOR is needed. The data is the converter to JSON if needed, using the standard CBOR rules.
The implementation is easy for the interger type salt
, as CBOR has numbers. But for the object, we want the serializer to do the work for as. To do this, we make use of the SerializationHelper that is available via the helper() method.
We pass 3 arguments to the SerializationHelper::serializeSubtype method. The first one is the type of what we want to get serialized. In this case, a pointer to QObject. The second is the actual value, converted to QVariant. The third parameter is a hint in case of an exception. It basically means: If something goes wrong it was somewhere in the "object" field of the Foo class.
This method contains the actual code to convert a CBOR object into our c++ Foo object. Again, since JSON and CBOR are compatible, JSON data is simply converted to CBOR and then handled by this method. However, some types need special handline, which is why the deserializeJson() is provided as well. See The deserializeJson
method for more details
This is easy for the interger type salt
, as cbor has numbers. But for the object, we want the serializer to do the work for as. To do this, we make use of the SerializationHelper that is available via the helper() method.
We pass 4 arguments to the SerializationHelper::serializeSubtype method. The first one is the type of what we want to get deserialized. In this case, a pointer to QObject. The second is the actual cbor value. The third argument is parent for the QObject. In our case, the Foo class owns the object, and thus the object should not have a parent, and we pass nullptr. The fourth parameter is a hint in case of an exception. It basically means: If something goes wrong it was somewhere in the "object" field of the Foo class.
In some cases, you want your CBOR data to be tagged. The The serialize
method section already shows how to tag data. For deserialization however, you may want to verify your data to make sure only data with a correct tag can be deserialized. Thats what the allowedCborTags method is for. For JSON deserialization, this method is ignored.
If your converter supports certain tags, you might be able to guess the C++ type from the tag. This can be very useful, when deserializing data without knowing the C++ type to deserialize it to. Since JSON has no tags, this method is ignored for json deserialization.
In some rare cases, important information is lost when converting from cbor to JSON. For example, if you use a QByteArray, it is converted to a base64url encoded string when converted to JSON. To deserialize such a value, extra information is needed, as the CBOR parser does not know the read data is a bytearray and not just a string.
You can use the deserializeJson() to handle such special cases:
Definition at line 39 of file typeconverter.h.
The possible results of canDeserialize(), used internally only.
Definition at line 58 of file typeconverter.h.
|
virtual |
Returns a list of allowed tags for the given type.
metaTypeId | The id of the type to get tags for |
If your converter uses tags, use this method to return relevant tags. If the list does not contain NoTag, deserialization will fail if the data has either no tag (only for strict deserialization) or a tag not in this list. Adding NoTag to the list makes sure data without a tag is always allowed even for the strict mode.
|
pure virtual |
Returns a list of allowed types for the given type and tag.
metaTypeId | The id of the type to get types for |
tag | The CBOR tag of the data to get types for |
The list should contain all types that are allowed for this specific type/tag combination. Your implementation must be able to deserialize any combination of the returned types and the given metaTypeId/tag. You can ignore the tag if you don't care about tags and the type if your converter only supports one type.
For JSON deserialization, the types are converter to JSON according to the table from QCborValue::toJsonValue
|
pure virtual |
Returns true, if this implementation can convert the given type.
metaTypeId | The id of the type to be converted |
If you return true for this method, it is expected your implementation can successfully de/serialize any valid instance for the given type. If you can't, serialization will fail, and no other converter get's a chance to try
|
pure virtual |
Called by the serializer to deserializer your given type from CBOR.
propertyType | The type of the data to deserialize |
value | The value to deserialize, as cbor value |
parent | A parent object, in case you create a QObject class you can pass it as parent |
DeserializationException | In case something goes wrong, invalid data, etc. |
This method contains your actual converter code to transform CBOR (or JSON) data to a C++ data type to the. Use the helper() and given inputs to perform that conversion.
|
virtual |
Called by the serializer to deserializer your given type from JSON.
propertyType | The type of the data to deserialize |
value | The value to deserialize, as cbor value |
parent | A parent object, in case you create a QObject class you can pass it as parent |
DeserializationException | In case something goes wrong, invalid data, etc. |
This method contains your actual converter code to transform CBOR (or JSON) data to a C++ data type to the. Use the helper() and given inputs to perform that conversion.
|
virtual |
Returns a type guessed from the tag and data, that is supported by the converter.
tag | The CBOR tag of the data to get the C++ type for |
dataType | The CBOR data type of the data to get the C++ type for |
If your converter supports tags, and you deserialize data without providing the C++ type to deserialize it to, this method is used to guess the C++ type from the tag and the data type.
If you support a combination of a tag and data type, and it matches a unique C++ type your converter supports, return the metaTypeId of that type. Otherwise return QMetaType::UnknownType to indicate your converter does not understand the data.
QtJsonSerializer::TypeConverter::helper | ( | ) | const |
Returns the helper associated with this converter.
The helper returned by this method is always valid, except from the constructor. It can be used to de/serialize subtypes and obtain other information useful for a converter from the serializer that is using the converter.
QtJsonSerializer::TypeConverter::priority | ( | ) | const |
Returns the priority of this converter.
The priority is important for cases where multiple converters can handle the same type. The converter with the highest priority wins. The default value is 0, and so are all converters internally used by the library. The property can be set either by your implementation (i.e. in the constructor), or dynamically before adding the converter to a serializer.
|
pure virtual |
Called by the serializer to serializer your given type to CBOR.
propertyType | The type of the data to serialize |
value | The value to serialize, wrapped as QVariant |
SerializationException | In case something goes wrong, invalid data, etc. |
This method contains your actual converter code to transform a C++ data type to the CBOR representation. Use the helper() and given inputs to perform that conversion.
QtJsonSerializer::TypeConverter::setPriority | ( | int | priority | ) |
Sets the priority of this converter.
priority | The priority of the converter |
The priority is important for cases where multiple converters can handle the same type. The converter with the highest priority wins. The default value is 0, and so are all converters internally used by the library. The property can be set either by your implementation (i.e. in the constructor), or dynamically before adding the converter to a serializer.