Monday, August 19, 2013

BB10 / Qt : How to serialize any user defined QObject class to QByteArray using QDataStream

Today I am going to write about how to serialize any QObject class and then write the object to a byte array and desalinize it back from the byte array. This is crucial if you want to send any object over the net or save it in a file or database.

First, we need a base class which make all of it's subclass serializable.

SerializableClass.h
#ifndef SerializableClass_H_
#define SerializableClass_H_
#include <qt4/QtCore/qobject.h>
#include <qt4/QtCore/qdatastream.h>
class SerializableClass : public QObject
{
    Q_OBJECT
public:
    explicit SerializableClass(QObject *parent = 0);

};
QDataStream &operator<<(QDataStream &ds, const SerializableClass &obj);
QDataStream &operator>>(QDataStream &ds, SerializableClass &obj) ;
#endif /* SerializableClass_H_ */
SerializableClass.cpp
#include "SerializableClass.h"
#include <qt4/Qt/qvariant.h>
#include <qt4/QtCore/qmetaobject.h>
SerializableClass::SerializableClass(QObject *parent) :
    QObject(parent)
{
}
QDataStream &operator<<(QDataStream &ds, const SerializableClass &obj) {
    for(int i=0; i<obj.metaObject()->propertyCount(); ++i)
    {
        if(obj.metaObject()->property(i).isStored(&obj))
        {
            ds << obj.metaObject()->property(i).read(&obj);
        }
    }
    return ds;
}
QDataStream &operator>>(QDataStream &ds, SerializableClass &obj) {
    QVariant var;
    for(int i=0; i<obj.metaObject()->propertyCount(); ++i)
    {
        if(obj.metaObject()->property(i).isStored(&obj))
        {
            ds >> var;
            obj.metaObject()->property(i).write(&obj, var);
        }
    }
    return ds;
}

Now, you need to extend this class to make your class serializable. Let's see as example.

Student.h
#ifndef STUDENT_H_
#define STUDENT_H_
#include "SerializableClass.h" 
class Student : public SerializableClass
{
    Q_OBJECT
    Q_PROPERTY(int id READ getId WRITE setId)
    Q_PROPERTY(QString Name READ getName WRITE setName)
public:
    Student();
    int getId() const { return id; }
    void setId(int newId) { id = newId; }
    QString getName() const { return Name; }
    void setName(const QString &newName) { Name = newName; }
private:
    int id;
    QString Name;
}; 
#endif /* STUDENT_H_ */

Student.cpp
#include "Student.h"
Student::Student()
{

Here Q_OBJECT, Q_PROPERTY macros are required to take care of generating proper metaObject for your class. Now we are going to put these classes in action at main() function.

main.cpp
Q_DECL_EXPORT int main(int argc, char **argv)
{
    Student G;
    Student G2;
   G.setId(30);
   G.setName("pervez");
   qDebug()<<G.getId()<<G.getName();
   QByteArray byteArray;
   QDataStream out(&byteArray, QIODevice::WriteOnly);
   out <<G;
   qDebug()<<G2.getId()<<G2.getName();
   QDataStream in(byteArray);
   in >> G2;
   qDebug()<<G2.getId()<<G2.getName();

   Application app(argc, argv);
   new ApplicationUI(&app);
   return Application::exec();
}

Here QDataStream out writes the G object in byteArray at "out <<G;" statement. that's why we use >> and << operator in SerializableClass.h header file


No comments:

Post a Comment