Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

qt xml Serialize funtion



  • Can you check the serialization function I implemented?
    The problem is that I can't get the data stored according to the inheritance relationship.

    cSerializer.h

    #define GET(prefix, name) get_##prefix##_##name
    #define SET(prefix, name) set_##prefix##_##name
    
    
    
    /* Create variable */
    #define QS_DECLARE_MEMBER(type, name)                                                       \
        public :                                                                                \
        type name = type();                                                                     \
    
    
    
    /* Create XML property and methods for primitive type field*/
    #define QS_XML_FIELD(type, name)                                                            \
        Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name))                      \
        private:                                                                                \
        QDomNode GET(xml, name)() const                                                         \
        {                                                                                       \
            QDomDocument doc;                                                                   \
            QString strname = #name;                                                            \
            QDomElement element = doc.createElement(strname);                                   \
            QDomText valueOfProp = doc.createTextNode(QVariant(name).toString());               \
            element.appendChild(valueOfProp);                                                   \
            doc.appendChild(element);                                                           \
            return  QDomNode(doc);                                                          \
        }                                                                                       \
        void SET(xml, name)(const QDomNode &node)                                               \
        {                                                                                       \
            if(!node.isNull() && node.isElement())                                              \
            {                                                                                   \
                QDomElement domElement = node.toElement();                                      \
                if(domElement.tagName() == #name)                                               \
                {                                                                               \
                    name = QVariant(domElement.text()).value<type>();                           \
                }                                                                               \
            }                                                                                   \
        }                                                                                     
         
    
    
    /* Generate XML-property and methods for primitive type objects */
    /* This collection must be provide method append(T) (it's can be QList, QVector)    */
    #define QS_XML_ARRAY(itemType, name)                                                        \
        Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name))                      \
        private:                                                                                \
            QDomNode GET(xml, name)() const                                                     \
            {                                                                                   \
                QDomDocument doc;                                                               \
                QString strname = #name;                                                        \
                QDomElement arrayXml = doc.createElement(QString(strname));                     \
                arrayXml.setAttribute("type", "array");                                         \
                                                                                                \
                for(int i = 0; i < name.size(); i++) {                                          \
                    itemType item = name.at(i);                                                 \
                    QDomElement itemXml = doc.createElement("item");                            \
                    itemXml.setAttribute("type", #itemType);                                    \
                    itemXml.setAttribute("index", i);                                           \
                    itemXml.appendChild(doc.createTextNode(QVariant(item).toString()));         \
                    arrayXml.appendChild(itemXml);                                              \
                }                                                                               \
                                                                                                \
                doc.appendChild(arrayXml);                                                      \
                return  QDomNode(doc);                                                          \
            }                                                                                   \
            void SET(xml, name)(const QDomNode & node) {                                        \
                QDomNode domNode = node.firstChild();                                           \
                name.clear();                                                                   \
                while(!domNode.isNull()) {                                                      \
                    if(domNode.isElement()) {                                                   \
                        QDomElement domElement = domNode.toElement();                           \
                        name.append(QVariant(domElement.text()).value<itemType>());             \
                    }                                                                           \
                    domNode = domNode.nextSibling();                                            \
                }                                                                               \
            }
    
    
    
    /* Generate XML-property and methods for some custom class */
    /* Custom type must be provide methods fromJson and toJson or inherit from QSerializer */
    #define QS_XML_OBJECT(type, name)                                                           \
        Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name))                      \
        private:                                                                                \
            QDomNode GET(xml, name)() const                                                     \
            {                                                                                   \
                qDebug() << QString("QS_GET_XML_OBJECT");       \
                return name.toXml();                                                            \
            }                                                                                   \
            void SET(xml, name)(const QDomNode & node)                                          \
            {                                                                                   \
                qDebug() << QString("QS_SET_XML_OBJECT");       \
                name.fromXml(node);                                                             \
            }                                                                                   
    
    
    
    /* Generate XML-property and methods for collection of custom type objects  */
    /* Custom type must be provide methods fromXml and toXml or inherit from QSerializer */
    /* This collection must be provide method append(T) (it's can be QList, QVector)    */
    #define QS_XML_ARRAY_OBJECTS(itemType, name)                                                \
        Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name))                      \
        private:                                                                                \
        QDomNode GET(xml, name)() const {                                                       \
            QDomDocument doc;                                                                   \
            QDomElement element = doc.createElement(#name);                                     \
            element.setAttribute("type", "array");                                              \
            for(int i = 0; i < name.size(); i++)                                                \
                element.appendChild(name.at(i).toXml());                                        \
            doc.appendChild(element);                                                           \
            return QDomNode(doc);                                                               \
        }                                                                                       \
        void SET(xml, name)(const QDomNode & node) {                                            \
            name.clear();                                                                       \
            QDomNodeList nodesList = node.childNodes();                                         \
            for(int i = 0;  i < nodesList.size(); i++) {                                        \
                itemType tmp;                                                                   \
                tmp.fromXml(nodesList.at(i));                                                   \
                name.append(tmp);                                                               \
            }                                                                                   \
        }                                                                                       
    
    
    
    /* Generate XML-property and methods for dictionary of simple fields (int, bool, QString, ...)  */
    /* Custom type must be inherit from QSerializer */
    /* This collection must be provide method insert(KeyT, ValueT) (it's can be QMap, QHash)    */
    /* THIS IS FOR QT DICTIONARY TYPES, for example QMap<int, QString>, QMap<int,int>, ...*/
    #define QS_XML_QT_DICT(map, name)                                                                       \
        Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name))                                  \
        private:                                                                                            \
        QDomNode GET(xml, name)() const {                                                                   \
            QDomDocument doc;                                                                               \
            QDomElement element = doc.createElement(#name);                                                 \
            element.setAttribute("type", "map");                                                            \
            for(auto p = name.begin(); p != name.end(); ++p)                                                \
            {                                                                                               \
                QDomElement e = doc.createElement("item");                                                  \
                e.setAttribute("key", QVariant(p.key()).toString());                                        \
                e.setAttribute("value", QVariant(p.value()).toString());                                    \
                element.appendChild(e);                                                                     \
            }                                                                                               \
            doc.appendChild(element);                                                                       \
            return QDomNode(doc);                                                                           \
        }                                                                                                   \
        void SET(xml, name)(const QDomNode & node) {                                                        \
            if(!node.isNull() && node.isElement())                                                          \
            {                                                                                               \
                QDomElement root = node.toElement();                                                        \
                if(root.tagName() == #name)                                                                 \
                {                                                                                           \
                    QDomNodeList childs = root.childNodes();                                                \
                                                                                                            \
                    for(int i = 0; i < childs.size(); ++i) {                                                \
                    QDomElement item = childs.at(i).toElement();                                            \
                    name.insert(QVariant(item.attributeNode("key").value()).value<map::key_type>(),         \
                                QVariant(item.attributeNode("value").value()).value<map::mapped_type>());   \
                    }                                                                                       \
                }                                                                                           \
            }                                                                                               \
        }                                                                                                   
    
    
    
    /* Generate XML-property and methods for dictionary of custom type objects  */
    /* Custom type must be inherit from QSerializer */
    /* This collection must be provide method insert(KeyT, ValueT) (it's can be QMap, QHash)    */
    /* THIS IS FOR QT DICTIONARY TYPES, for example QMap<int, CustomSerializableType> */
    #define QS_XML_QT_DICT_OBJECTS(map, name)                                                               \
        Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name))                                  \
        private:                                                                                            \
        QDomNode GET(xml, name)() const {                                                                   \
            QDomDocument doc;                                                                               \
            QDomElement element = doc.createElement(#name);                                                 \
            element.setAttribute("type", "map");                                                            \
            for(auto p = name.begin(); p != name.end(); ++p)                                                \
            {                                                                                               \
                QDomElement e = doc.createElement("item");                                                  \
                e.setAttribute("key", QVariant(p.key()).toString());                                        \
                e.appendChild(p.value().toXml());                                                           \
                element.appendChild(e);                                                                     \
            }                                                                                               \
            doc.appendChild(element);                                                                       \
            return QDomNode(doc);                                                                           \
        }                                                                                                   \
        void SET(xml, name)(const QDomNode & node) {                                                        \
            if(!node.isNull() && node.isElement())                                                          \
            {                                                                                               \
                QDomElement root = node.toElement();                                                        \
                if(root.tagName() == #name)                                                                 \
                {                                                                                           \
                    QDomNodeList childs = root.childNodes();                                                \
                                                                                                            \
                    for(int i = 0; i < childs.size(); ++i) {                                                \
                    QDomElement item = childs.at(i).toElement();                                            \
                    map::mapped_type tmp;                                                                   \
                    tmp.fromXml(item.firstChild());                                                         \
                    name.insert(QVariant(item.attributeNode("key").value()).value<map::key_type>(),         \
                                tmp);                                                                       \
                    }                                                                                       \
                }                                                                                           \
            }                                                                                               \
        }                                                                                                   
    
    
    
    #define QS_XML_STL_DICT(map, name)                                                                       \
        Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name))                                  \
        private:                                                                                            \
        QDomNode GET(xml, name)() const {                                                                   \
            QDomDocument doc;                                                                               \
            QDomElement element = doc.createElement(#name);                                                 \
            element.setAttribute("type", "map");                                                            \
            for(auto p : name)                                                                              \
            {                                                                                               \
                QDomElement e = doc.createElement("item");                                                  \
                e.setAttribute("key", QVariant(p.first).toString());                                        \
                e.setAttribute("value", QVariant(p.second).toString());                                     \
                element.appendChild(e);                                                                     \
            }                                                                                               \
            doc.appendChild(element);                                                                       \
            return QDomNode(doc);                                                                           \
        }                                                                                                   \
        void SET(xml, name)(const QDomNode & node) {                                                        \
            if(!node.isNull() && node.isElement())                                                          \
            {                                                                                               \
                QDomElement root = node.toElement();                                                        \
                if(root.tagName() == #name)                                                                 \
                {                                                                                           \
                    QDomNodeList childs = root.childNodes();                                                \
                                                                                                            \
                    for(int i = 0; i < childs.size(); ++i) {                                                \
                    QDomElement item = childs.at(i).toElement();                                            \
                    name.insert(std::pair<map::key_type, map::mapped_type>(                                 \
                                QVariant(item.attributeNode("key").value()).value<map::key_type>(),         \
                                QVariant(item.attributeNode("value").value()).value<map::mapped_type>()));  \
                    }                                                                                       \
                }                                                                                           \
            }                                                                                               \
        }                                                                                                   
    
    
    
    /* Generate XML-property and methods for dictionary of custom type objects */
    /* Custom type must be inherit from QSerializer */
    /* This collection must be provide method insert(KeyT, ValueT) (it's can be std::map)    */
    /* THIS IS FOR STL DICTIONARY TYPES, for example std::map<int, CustomSerializableType> */
    #define QS_XML_STL_DICT_OBJECTS(map, name)                                                              \
        Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name))                                  \
        private:                                                                                            \
        QDomNode GET(xml, name)() const {                                                                   \
            QDomDocument doc;                                                                               \
            QDomElement element = doc.createElement(#name);                                                 \
            element.setAttribute("type", "map");                                                            \
            for(auto p : name)                                                \
            {                                                                                               \
                QDomElement e = doc.createElement("item");                                                  \
                e.setAttribute("key", QVariant(p.first).toString());                                        \
                e.appendChild(p.second.toXml());                                                            \
                element.appendChild(e);                                                                     \
            }                                                                                               \
            doc.appendChild(element);                                                                       \
            return QDomNode(doc);                                                                           \
        }                                                                                                   \
        void SET(xml, name)(const QDomNode & node) {                                                        \
            if(!node.isNull() && node.isElement())                                                          \
            {                                                                                               \
                QDomElement root = node.toElement();                                                        \
                if(root.tagName() == #name)                                                                 \
                {                                                                                           \
                    QDomNodeList childs = root.childNodes();                                                \
                                                                                                            \
                    for(int i = 0; i < childs.size(); ++i) {                                                \
                    QDomElement item = childs.at(i).toElement();                                            \
                    map::mapped_type tmp;                                                                   \
                    tmp.fromXml(item.firstChild());                                                         \
                    name.insert(std::pair<map::key_type, map::mapped_type> (                                \
                                QVariant(item.attributeNode("key").value()).value<map::key_type>(),         \
                                tmp));                                                                      \
                    }                                                                                       \
                }                                                                                           \
            }                                                                                               \
        }                                                                                                   
    
    
    
    /* Create variable */
    #define QS_DECLARE_MEMBER(type, name)                                                       \
        public :                                                                                \
        type name = type();   
    
    
                             
    /* BIND: */
    /* generate serializable propertyes JSON and XML for primitive type field */
    #define QS_BIND_FIELD(type, name)                                                           \
        QS_XML_FIELD(type, name)  
    
    
    
    /* BIND: */
    /* generate serializable propertyes JSON and XML for collection of primitive type fields */
    #define QS_BIND_COLLECTION(itemType, name)                                                  \
        QS_XML_ARRAY(itemType, name)    
    
    
    
    /* BIND: */
    /* generate serializable propertyes JSON and XML for custom type object */
    #define QS_BIND_OBJECT(type, name)                                                          \
        QS_XML_OBJECT(type, name)  
    
    
    
    /* BIND: */
    /* generate serializable propertyes JSON and XML for collection of custom type objects */
    #define QS_BIND_COLLECTION_OBJECTS(itemType, name)                                          \
        QS_XML_ARRAY_OBJECTS(itemType, name)                                                    \
    
    
    
    /* BIND: */
    /* generate serializable propertyes JSON and XML for dictionary with primitive value type for QT DICTIONARY TYPES */
    #define QS_BIND_QT_DICT(map, name)                                                         \
        QS_XML_QT_DICT(map, name)                                                              \
    
    
    
    /* BIND: */
    /* generate serializable propertyes JSON and XML for dictionary of custom type objects for QT DICTIONARY TYPES */
    #define QS_BIND_QT_DICT_OBJECTS(map, name)                                                 \
        QS_XML_QT_DICT_OBJECTS(map,name)                                                       \
    
    
    
    /* BIND: */
    /* generate serializable propertyes JSON and XML for dictionary with primitive value type for STL DICTIONARY TYPES */
    #define QS_BIND_STL_DICT(map, name)                                                         \
        QS_XML_STL_DICT(map, name)                                                              \
    
    
    
    /* BIND: */
    /* generate serializable propertyes JSON and XML for dictionary of custom type objects for STL DICTIONARY TYPES */
    #define QS_BIND_STL_DICT_OBJECTS(map, name)                                                 \
        QS_XML_STL_DICT_OBJECTS(map,name)                                                       \
    
    
    
    /* CREATE AND BIND: */
    /* Make primitive field and generate serializable propertyes */
    /* For example: QS_FIELD(int, digit), QS_FIELD(bool, flag) */
    #define QS_FIELD(type, name)                                                                \
        QS_DECLARE_MEMBER(type, name)                                                           \
        QS_BIND_FIELD(type, name)  
    
    
    
    /* CREATE AND BIND: */
    /* Make primitive field and generate serializable propertyes */
    /* For example: QS_FIELD(int, digit), QS_FIELD(bool, flag) */
    #define QS_FIELD(type, name)                                                                \
        QS_DECLARE_MEMBER(type, name)                                                           \
        QS_BIND_FIELD(type, name)                                                               \
    
    
    
    /* CREATE AND BIND: */
    /* Make collection of primitive type objects [collectionType<itemType> name] and generate serializable propertyes for this collection */
    /* This collection must be provide method append(T) (it's can be QList, QVector)    */
    #define QS_COLLECTION(collectionType, itemType, name)                                       \
        QS_DECLARE_MEMBER(collectionType<itemType>, name)                                       \
        QS_BIND_COLLECTION(itemType, name)                                                      \
    
    
    
    /* CREATE AND BIND: */
    /* Make custom class object and bind serializable propertyes */
    /* This class must be inherited from QSerializer */
    #define QS_OBJECT(type,name)                                                                \
        QS_DECLARE_MEMBER(type, name)                                                           \
        QS_BIND_OBJECT(type, name)                                                              \
    
    
    
    /* CREATE AND BIND: */
    /* Make collection of custom class objects [collectionType<itemType> name] and bind serializable propertyes */
    /* This collection must be provide method append(T) (it's can be QList, QVector)    */
    #define QS_COLLECTION_OBJECTS(collectionType, itemType, name)                               \
        QS_DECLARE_MEMBER(collectionType<itemType>, name)                                       \
        QS_BIND_COLLECTION_OBJECTS(itemType, name)                                              \
    
    

    **** cModelStructure.h ****

    class cModelStandardCurve_MeasureData : public cSerializer
    {
    	Q_GADGET
    		QS_SERIALIZABLE
    
    private:
    		QS_FIELD(bool, IsChecked)								//	체크박스 상태
    		QS_COLLECTION(QVector, qreal, vABS)						//	흡광도
    		QS_COLLECTION(QVector, qreal, vConc)					//	농도
    		QS_COLLECTION(QVector, qreal, vDispExp)					//	차트 axis?
    		QS_COLLECTION(QVector, qreal, vCalcExp)					//	수식
    };
    
    
    class cModelStandardCurve : public cModelCommon
    {
    	Q_GADGET
    		QS_SERIALIZABLE
    		QS_FIELD(int, nFactor)										//	희석배수
    		QS_FIELD(int, nSTCType)										//	STC 타입 
    		QS_FIELD(int, nRSQ)											//	RSQ
    
    		QS_OBJECT(cModelStandardCurve_MeasureData, cSTC_MeasureData)	//	측정결과
    		QS_OBJECT(cReportOption, cSTC_Reportopt)						//	리포트옵션
    };
    
    
    class cModelQuantitation_MeasureData : public cSerializer
    {
    	Q_GADGET
    		QS_SERIALIZABLE
    
    		QS_FIELD(bool, IsChecked)								//	체크박스 상태
    		QS_COLLECTION(QVector, qreal, vConc)					//	농도
    		QS_COLLECTION(QVector, qreal, vTRA)						//	투과율
    		QS_COLLECTION(QVector, qreal, vABS)						//	흡광도
    		QS_COLLECTION(QVector, QString, vCellNumber)			//	셀번호
    		QS_FIELD(QString, strSampleName)						//	샘플명
    		QS_FIELD(double, strTemperature)						//	온도
    };
    
    
    class cModelQuantitation : public cModelCommon
    {
    	Q_GADGET
    		QS_SERIALIZABLE
    		QS_OBJECT(cModelQuantitation_MeasureData,	cMeasureData)	 //	측정결과
    		QS_OBJECT(cReportOption,					cReportopt)		 //	리포트옵션
    		QS_OBJECT(cModelStandardCurve,				cStandardCurve)	 //	STC정보
    };
    
    
    void cSerializer::fromXml(const QDomNode& val)
    {
    	QDomNode doc = val;
    
    	const char* className = metaObject()->className();
    	auto n = doc.firstChildElement(metaObject()->className());
    
    	qDebug() << QString("******* %1 *******").arg(className);
    
    	if (!n.isNull()) 
    	{
    		// 
    		for (int i = 0; i < metaObject()->propertyCount(); i++) 
    		{
    			QDomElement tmp = metaObject()->property(i).readOnGadget(this).value<QDomNode>().firstChildElement();
    			auto f = n.firstChildElement(tmp.tagName());			
    			qDebug() << QString("%1: %2").arg(tmp.tagName()).arg(f.text().toUtf8().constData());
    			metaObject()->property(i).writeOnGadget(this, QVariant::fromValue<QDomNode>(f));
    		}
    	}
    	else
    	{
    		for (int i = 0; i < metaObject()->propertyCount(); i++) 
    		{
    			QString name = metaObject()->property(i).name();
    			auto f = doc.firstChildElement(name);
    			qDebug() << QString("%1: %2").arg(name).arg(f.text().toUtf8().constData());
    			QString str = f.text();
    			if (str.isNull())
    				continue;				
    			metaObject()->property(i).writeOnGadget(this, QVariant::fromValue<QDomNode>(f));
    		}
    	}
    }
    


  • https://github.com/smurfomen/QSerializer

    The source code can be obtained here.


Log in to reply