DeeSerializable

## DeeSerializable DeeSerializable — Interface for classes that can serialize to and from GVariants |

## Synopsis

    #include <dee.h>

    struct              DeeSerializableIface;
    GObject *           (*DeeSerializableParseFunc)         (GVariant *data);
    GVariant *          dee_serializable_externalize        (DeeSerializable *self);
    GObject *           dee_serializable_parse              (GVariant *data,
                                                             GType type);
    GObject *           dee_serializable_parse_external     (GVariant *data);
    void                dee_serializable_register_parser    (GType type,
                                                             const GVariantType *vtype,
                                                             DeeSerializableParseFunc parse_func);
    GVariant *          dee_serializable_serialize          (DeeSerializable *self);

## Description

Interface for classes that can serialize to and from GVariants.

There are two serialization concepts supported by this API: serialization and externalization. A serialized instance is created with `dee_serializable_serialize()` and can be read back with `dee_serializable_parse()` provided you know the correct GType for the serialized data. The GVariant representation of your serialized data is guaranteed to be exactly as you implement yourself in the `serialize` vfunc of the DeeSerializableIface.

With externalized instances you don't have to know the correct GType to recreate the instance. The GType is encoded in the data itself. When you're using `dee_serializable_externalize()` your data will be wrapped in a container format with the required object metadata to read it back. For this reason `dee_serializable_parse_external()` doesn't require you to pass in the GType you want to deserialize.

### On Subclasses of DeeSerializable Types

As a rule of thumb you need to re-implement the DeeSerializable interface and install parse functions with `dee_serializable_register_parser()` every time you create a new class derived from a DeeSerializable superclass.

In case a subclass does not provide it's own serialization interface Dee will recurse upwards in the type hierarchy and use the serialization and parser implementations of the first superclass with the required behaviour. This means that the parsed instance will not be an instance of the subclass but only of the serializable superclass. Caveat emptor.

## Details

### struct DeeSerializableIface

    struct DeeSerializableIface {
      GTypeInterface g_iface;

      GVariant*       (*serialize)         (DeeSerializable *self);
    };

### DeeSerializableParseFunc ()

    GObject *           (*DeeSerializableParseFunc)         (GVariant *data);

`data` : | A GVariant with type signature as passed to `dee_serializable_register_parser()` when the parser was registered. The variant is not referenced.
Returns : | A newly constructed GObject of the GType used when registering the parser. Note that since the environment guarantees that the input data is valid according to the registration information this function can not fail. Thus `NULL` is not a valid return value. [transfer full]

### dee_serializable_externalize ()

    GVariant *          dee_serializable_externalize        (DeeSerializable *self);

Build an externalized form of `self` which can be used together with `dee_serializable_parse_external()` to rebuild a copy of `self`.

It is important to note that the variant returned from this method does not have the same type signature as returned from a call to `dee_serializable_serialize()`. Externalization will wrap the serialized data in a container format with versioning information and headers with type information.

`self` : | The instance to externalize
Returns : | A floating reference to a GVariant with the externalized data.

### dee_serializable_parse ()

    GObject *           dee_serializable_parse              (GVariant *data,
                                                             GType type);

Reconstruct a DeeSerializable from GVariant data. For this function to work you need to register a parser with `dee_serializable_register_parser()`. Any native Dee class will do so automatically.

This method only works on data created with `dee_serializable_serialize()` and not with data from `dee_serializable_externalize()`.

Since a DeeSerializableParseFunc is not allowed to fail - by contract - it can be guaranteed that this function only returns `NULL` in case there is no known parser for `type` and GVariant signature of `data`.

`data` : | The GVariant data to parse. If this is a floating reference it will be consumed
`type` : | The GType of the class to instantiate from `data`
Returns : | A newly constructed GObject build from `data` or `NULL` in case no parser has been registered for the given GType or variant signature. Free with `g_object_unref()`. [transfer full]

### dee_serializable_parse_external ()

    GObject *           dee_serializable_parse_external     (GVariant *data);

Reconstruct a DeeSerializable from GVariant data. For this function to work you need to register a parser with `dee_serializable_register_parser()`. Any native Dee class will do so automatically.

This method only works on data created with `dee_serializable_externalize()` and not with data from `dee_serializable_serialize()`.

Since a DeeSerializableParseFunc is not allowed to fail - by contract - it can be guaranteed that this function only returns `NULL` in case there is no known parser for the GType or GVariant signature of `data`.

`data` : | The GVariant data to parse
Returns : | A newly constructed GObject build from `data` or `NULL` in case no parser has been registered for the given GType or variant signature. Free with `g_object_unref()`. [transfer full]

### dee_serializable_register_parser ()

    void                dee_serializable_register_parser    (GType type,
                                                             const GVariantType *vtype,
                                                             DeeSerializableParseFunc parse_func);

Register a parser that can convert GVariant data into an instance of a given GType. Note that you can register more than one parser for the same GType provided that you give them different variant type signatures.

If there is already a parser registered for the given `type` and `vtype` it will be silently replaced.

The recommended behaviour is that GObject classes register their parsers in their respective class init functions.

`type` : | The GType of the object class to register a parser for
`vtype` : | Variants to be converted must have this signature
`parse_func` : | A function to convert GVariant data into an instance of the given `type`.

### dee_serializable_serialize ()

    GVariant *          dee_serializable_serialize          (DeeSerializable *self);

Build a clean serialized representation of `self`. The signature of the returned variant is entirely determined by the underlying implementation. You can recreate a serialized instance by calling `dee_serializable_parse()` provided that you know the correct GType for the serialized instance.

`self` : | The instance to serialize
Returns : | A reference to a GVariant with the serialized data. The variants type signature is entirely dependent of the underlying implementation. Free using `g_variant_unref()`. [transfer full]