Custom class serialize with QDataStream



  • Hi Everybody,

    I have got a TreeItem custom class (not derived from QObject) which is "wrapped" into QVariant and i would like to serialize and deserialize it with QDataStream.
    TreeItem represents a multi-level Tree with a list of child pointers and a parent pointer.
    I placed the implemented operator<< and operator>> methods before main() method and qRegisterMetaTypeStreamOperators<TreeItem>("TreeItem"); in the first line of main() method.
    I have defined a Q_DECLARE_METATYPE(TreeItem*) macro too.

    See above:

    #include "TheApp.h"
    #include <QtWidgets/QApplication>
    #include "TreeItem.h"
    
    QDataStream &operator<<(QDataStream &out, const TreeItem &rhs) {
       out.writeRawData(reinterpret_cast<const char*>(&rhs), sizeof(rhs));
       return out;
    }
    
    QDataStream &operator>>(QDataStream &in, TreeItem &rhs) {
       in.readRawData(reinterpret_cast<char*>(&rhs), sizeof(rhs));
       return in;
    }
    
    int main(int argc, char *argv[])
    {
       QApplication a(argc, argv);
       qRegisterMetaTypeStreamOperators<TreeItem>("TreeItem");
       QCoreApplication::setApplicationName(QString("TheApp"));
       TheApp w;
       w.show();
       return a.exec();
    }
    

    I would like to encode it with the following:

    QByteArray encodedData;
    QDataStream stream(&encodedData, QIODevice::WriteOnly);
    TreeItem* treeItem = new TreeItem();
    QVariant treeItemQVariant = QVariant::fromValue(treeItem);
    stream << treeItemQVariant;
    

    When i execute "stream << treeItemQVariant;" i got this error message:

       QVariant::save: unable to save type 'TreeItem*' (type id: 1037).
       ASSERT failure in QVariant::save: "Invalid type to save", file kernel\qvariant.cpp, line 2144
       Debug Error!
    

    What is the problem?
    How can i (de)serialize a custom class with QDataStream which is "wrapped" into a QVariant?

    Thanks in advance,
    It should be a big help for me,
    BR,
    Peter



  • I don't like your serialisation with reinterpret_cast but the main point here is that you are getting confused by the pointer.

    change Q_DECLARE_METATYPE(TreeItem*) to Q_DECLARE_METATYPE(TreeItem)
    and change QVariant treeItemQVariant = QVariant::fromValue(treeItem); to QVariant treeItemQVariant = QVariant::fromValue(*treeItem); (be carefull not to leak treeItem)

    @pvt.peter said in Custom class serialize with QDataStream:

    How can i (de)serialize a custom class with QDataStream which is "wrapped" into a QVariant?

    QVariant TempVariant;
    stream >> TempVariant;
    *treeItem = TempVariant.value<TreeItem>();
    

    P.S.
    in your code snippet you don't really need to pass through QVariant btw, you can just use stream << *treeItem;



  • @VRonin Thanks for your reply, i did your modifications and it works with QVariant.

    But how can i use stream << *treeItem; ?
    Now i use the following codes:

    Q_DECLARE_METATYPE(TreeItem)
    

    QDataStream &operator<<(QDataStream &out, const TreeItem& rhs) {
       out.writeRawData(reinterpret_cast<const char*>(&rhs), sizeof(rhs));
       return out;
    }
    QDataStream &operator>>(QDataStream &in, TreeItem &rhs) {
       in.readRawData(reinterpret_cast<char*>(&rhs), sizeof(rhs));
       return in;
    }
    

    qRegisterMetaTypeStreamOperators<TreeItem>("TreeItem");
    

    TreeItem* treeItem = new TreeItem();
    stream << *treeItem;
    

    TreeItem* data2 = nullptr;
    while (!stream.atEnd()) {
       stream >> *data2;
    }
    

    There are some trouble with operator << and operator >>.
    No 'operator <<' matches arguments of type 'QDataStream' and 'TreeItem'
    No 'operator >>' matches arguments of type 'QDataStream' and 'TreeItem'
    How can i fix them?



  • You just have to declare the prototype QDataStream &operator<<(QDataStream &, const TreeItem& ) in the header file of TreeItem



  • Hi @VRonin,

    Thanks for your reply. Your answer was the solution.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.