GithubHelp home page GithubHelp logo

smurfomen / qserializer Goto Github PK

View Code? Open in Web Editor NEW
67.0 6.0 24.0 9.82 MB

This repo for Qt/C++ serialization objects in JSON or XML based on QtCore

Home Page: https://smurfomen.github.io/QSerializer/

License: MIT License

QMake 2.81% C++ 97.19%
qt json cpp serialization xml macro meta

qserializer's Introduction

logo This project is designed to convert data from an object view to JSON or XML and opposite in the Qt/C++ ecosystem. C ++ classes by default do not have the required meta-object information for serializing class fields, but Qt is equipped with its own highly efficient meta-object system. An important feature of the QSerializer is the ability to specify serializable fields of the class without having to serialize the entire class. QSerilaizer generate code and declare Q_PROPERTY for every declared member of class. This is convenient because you do not need to create separate structures or classes for serialization of write some code to serialize every class, it's just included to QSerializer.

Installation

Download repository

$ git clone https://github.com/smurfomen/QSerializer.git

Just include qserializer.h in your project and enjoy simple serialization. qserializer.h located in src folder. Set compiler define QS_HAS_JSON or QS_HAS_XML for enabling support for xml or json. Enable both at the same time is not supported.


A demo project for using QSerializer located in example folder.

Workflow

To get started, include qserializer.h in your code.

Create serialization class

For create serializable member of class and generate propertyes, use macro:

  • QS_FIELD
  • QS_COLLECTION
  • QS_OBJECT
  • QS_COLLECTION_OBJECTS
  • QS_QT_DICT
  • QS_QT_DICT_OBJECTS
  • QS_STL_DICT
  • QS_STL_DICT_OBJECTS

If you want only declare exists fields - use macro QS_JSON_FIELD, QS_XML_FIELD, QS_JSON_COLLECTION and other (look at qserializer.h)

Inherit from QSerializer

Inherit from QSerializer, use macro QS_SERIALIZABLE or override metaObject method and declare some serializable fields.
In this case you must use Q_GADGET in your class.

class User : public QSerializer
{
Q_GADGET
QS_SERIALIZABLE
// Create data members to be serialized - you can use this members in code
QS_FIELD(int, age)
QS_COLLECTION(QVector, QString, parents)
};

Serialize

Now you can serialize object of this class to JSON or XML. For example:

User u;
u.age = 20;
u.parents.append("Mary");
u.parents.append("Jeff");

/* case: json value */
QJsonObject jsonUser = u.toJson();

/* case: raw json data */
QByteArray djson = u.toRawJson();

/* case: xml-dom */
QDomNode xmlUser = u.toXml();

/* case: raw xml data */
QByteArray dxml = u.toRawXml();

Deserialize

Opposite of the serialization procedure is the deserialization procedure. You can deserialize object from JSON or XML, declared fields will be modified or resets to default for this type values. For example:

...
User u;

/* case: json value */
QJsonObject json;
u.fromJson(json);

/* case: raw json data */
QByteArray rawJson;
u.fromJson(rawJson);

/* case: xml-dom */
QDomNode xml;
u.fromXml(xml);

/* case: raw xml data */
QByteArray rawXml;
u.fromXml(rawXml);

Macro description

Macro Description
QSERIALIZABLE Make class or struct is serializable to QSerializer (override QMetaObject method and define Q_GADGET macro)
QS_FIELD Create serializable simple field
QS_COLLECTION Create serializable collection values of primitive types
QS_OBJECT Create serializable inner custom type object
QS_COLLECTION_OBJECTS Create serializable collection of custom type objects
QS_QT_DICT Create serializable dictionary of primitive type values FOR QT DICTIONARY TYPES
QS_QT_DICT_OBJECTS Create serializable dictionary of custom type values FOR QT DICTIONARY TYPES
QS_STL_DICT Create serializable dictionary of primitive type values FOR STL DICTIONARY TYPES
QS_STL_DICT_OBJECTS Create serializable dictionary of custom type values FOR STL DICTIONARY TYPES
QS_SERIALIZABLE Override method metaObject and make class serializable

qserializer's People

Contributors

smurfomen avatar xor-gate avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

qserializer's Issues

Qt Dictionaries

What is the problem with Qt dictionaries types (QHash, QMap...)?

Problems while writing

class cModelCommon : public cSerializer
{
	Q_GADGET
	QS_SERIALIZABLE

		QS_FIELD(QString, Name)
		QS_FIELD(QString, Memo)
		QS_FIELD(int, Time)
		QS_FIELD(int, Unit)
		QS_FIELD(QDateTime, DateTime)
		QS_COLLECTION(QVector, int, Wave_Length)
		QS_COLLECTION(QVector, int, Cell_type)
};

// [DeSerialize 과정]
    {
        QFile xml(strPath);
        if (!xml.exists())
            qWarning() << "ERROR: ModelCommon.xml is not exist";
        if (xml.open(QIODevice::ReadOnly))
        {
            // empty object
            cModelCommon src;
            qDebug() << "empty xml object:";
            //qDebug() << src.Serialize().constData();

            qDebug() << "contains in file: ModelCommon.xml";
            QByteArray d = xml.readAll();
            qDebug() << d << "\n";

            src.DeSerialize(d);
            qDebug() << "serialized json object from file: ModelCommon.xml";
            qDebug() << src.Serialize().constData();

            xml.close();
        }
    }

I even checked that I wrote about the newly defined variable and saved it as an xml file.
In the process of loading, it was discovered that the data for String could not be retrieved normally.
It seems to get the initial value through the process of GET in QS_XML_FIELD.

When I do xml.readAll();, I checked that the data was imported normally, but it seems to be missing in the process of writing. What is the problem?

=================================================================================

void cSerializer::fromXml(const QDomNode& val)
{
	QDomNode doc = val;

	const char* className = metaObject()->className();
	auto n = doc.firstChildElement(metaObject()->className());

	if (!n.isNull()) {
		for (int i = 0; i < metaObject()->propertyCount(); i++) 
		{
			QString name = metaObject()->property(i).name();
			QDomElement tmp = metaObject()->property(i).readOnGadget(this).value<QDomNode>().firstChildElement();

			QString str = tmp.tagName();

			//auto f = n.firstChildElement(tmp.tagName());
			**auto f = n.firstChildElement(name);**
			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);
			metaObject()->property(i).writeOnGadget(this, QVariant::fromValue<QDomNode>(f));
		}
	}
}

Why is tmp.tagName() empty? There is an error in retrieving data because of an empty part.

I've modified the source code, but when I edit it like this, it works normally.

Property is defined multiple times warning with MSVC 2019 and GCC on Qt 5

With QT Creator and MSVC 2019 compiler it complains a QS_FIELD or similar generates multiple definitions of the same class members. I have also tried this under ubuntu with GCC and I get no warnings only after turning on -Wextra, even outputting the intermediate code after preprocessing. I tried to analyze by hand and can not see why this problem occurs.

Warning output under Qt5.12.11 and MSVC 2019:

11:59:58: Running steps for project QSSerialize...
11:59:58: Configuration unchanged, skipping qmake step.
11:59:58: Starting: "C:\Qt\Qt5.12.11\Tools\QtCreator\bin\jom.exe" 
	C:\Qt\Qt5.12.11\Tools\QtCreator\bin\jom.exe -f Makefile.Debug
	cl -c -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -Zi -MDd -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -EHsc /Fddebug\QSSerialize.vc.pdb -DUNICODE -D_UNICODE -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DQSERIALIZER_INCLUDED -DQT_QML_DEBUG -DQT_XML_LIB -DQT_CORE_LIB -I..\QSSerialize -I. -I..\..\..\QSerializer -IC:\Qt\Qt5.12.11\5.12.11\msvc2017_64\include -IC:\Qt\Qt5.12.11\5.12.11\msvc2017_64\include\QtXml -IC:\Qt\Qt5.12.11\5.12.11\msvc2017_64\include\QtCore -Idebug -IC:\Qt\Qt5.12.11\5.12.11\msvc2017_64\mkspecs\win32-msvc -Fodebug\ @C:\Users\jjacobs\AppData\Local\Temp\main.obj.16312.0.jom
main.cpp
	C:\Qt\Qt5.12.11\5.12.11\msvc2017_64\bin\moc.exe -DUNICODE -D_UNICODE -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DQSERIALIZER_INCLUDED -DQT_QML_DEBUG -DQT_XML_LIB -DQT_CORE_LIB --compiler-flavor=msvc --include E:/src/github.com/smurfomen/QSerializer/example/build-QSSerialize-Desktop_Qt_5_12_11_MSVC2017_64bit-Debug/debug/moc_predefs.h -IC:/Qt/Qt5.12.11/5.12.11/msvc2017_64/mkspecs/win32-msvc -IE:/src/github.com/smurfomen/QSerializer/example/QSSerialize -IE:/src/github.com/smurfomen/QSerializer -IC:/Qt/Qt5.12.11/5.12.11/msvc2017_64/include -IC:/Qt/Qt5.12.11/5.12.11/msvc2017_64/include/QtXml -IC:/Qt/Qt5.12.11/5.12.11/msvc2017_64/include/QtCore -I. -I"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\ATLMFC\include" -I"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\shared" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\winrt" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\cppwinrt" ..\classes.h -o debug\moc_classes.cpp
..\classes.h(19): Warning: The property 'age' is defined multiple times in class Parent.
..\classes.h(19): Warning: The property 'name' is defined multiple times in class Parent.
..\classes.h(19): Warning: The property 'male' is defined multiple times in class Parent.
..\classes.h(38): Warning: The property 'age' is defined multiple times in class Student.
..\classes.h(38): Warning: The property 'name' is defined multiple times in class Student.
..\classes.h(38): Warning: The property 'links' is defined multiple times in class Student.
..\classes.h(38): Warning: The property 'parents' is defined multiple times in class Student.
..\classes.h(48): Warning: The property 'qt_hash' is defined multiple times in class Dictionaries.

GCC ubuntu warning:

/usr/lib/qt5/bin/moc -DQT_DEPRECATED_WARNINGS -DQSERIALIZER_INCLUDED -DQT_NO_DEBUG -DQT_XML_LIB -DQT_CORE_LIB --include /mnt/e/src/github.com/smurfomen/QSerializer/example/QSDeserialize/moc_predefs.h -I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++ -I/mnt/e/src/github.com/smurfomen/QSerializer/example/QSDeserialize -I/mnt/e/src/github.com/smurfomen/QSerializer -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtXml -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/c++/9 -I/usr/include/x86_64-linux-gnu/c++/9 -I/usr/include/c++/9/backward -I/usr/lib/gcc/x86_64-linux-gnu/9/include -I/usr/local/include -I/usr/include/x86_64-linux-gnu -I/usr/include ../classes.h -o moc_classes.cpp
../classes.h:19: Warning: The property 'age' is defined multiple times in class Parent.
../classes.h:19: Warning: The property 'name' is defined multiple times in class Parent.
../classes.h:19: Warning: The property 'male' is defined multiple times in class Parent.
../classes.h:38: Warning: The property 'age' is defined multiple times in class Student.
../classes.h:38: Warning: The property 'name' is defined multiple times in class Student.
../classes.h:38: Warning: The property 'links' is defined multiple times in class Student.
../classes.h:38: Warning: The property 'parents' is defined multiple times in class Student.
../classes.h:48: Warning: The property 'qt_hash' is defined multiple times in class Dictionaries.
../classes.h:48: Warning: The property 'qt_map' is defined multiple times in class Dictionaries.
../classes.h:48: Warning: The property 'qt_map_objects' is defined multiple times in class Dictionaries.
../classes.h:48: Warning: The property 'std_map' is defined multiple times in class Dictionaries.
../classes.h:48: Warning: The property 'std_map_objects' is defined multiple times in class Dictionaries.
../classes.h:58: Warning: The property 'digit' is defined multiple times in class Field.
../classes.h:58: Warning: The property 'string' is defined multiple times in class Field.
../classes.h:58: Warning: The property 'flag' is defined multiple times in class Field.
../classes.h:58: Warning: The property 'd_digit' is defined multiple times in class Field.
../classes.h:67: Warning: The property 'vector' is defined multiple times in class Collection.
../classes.h:67: Warning: The property 'list' is defined multiple times in class Collection.
../classes.h:67: Warning: The property 'stack' is defined multiple times in class Collection.
../classes.h:75: Warning: The property 'digit' is defined multiple times in class CustomObject.
../classes.h:75: Warning: The property 'string' is defined multiple times in class CustomObject.
../classes.h:82: Warning: The property 'objects' is defined multiple times in class CollectionOfObjects.
../classes.h:93: Warning: The property 'field' is defined multiple times in class General.
../classes.h:93: Warning: The property 'collection' is defined multiple times in class General.
../classes.h:93: Warning: The property 'object' is defined multiple times in class General.
../classes.h:93: Warning: The property 'collectionObjects' is defined multiple times in class General.
../classes.h:93: Warning: The property 'dictionaries' is defined multiple times in class General.
../classes.h:100: Warning: The property 'digit' is defined multiple times in class TestXmlObject.
../classes.h:100: Warning: The property 'string' is defined multiple times in class TestXmlObject.
../classes.h:108: Warning: The property 'field' is defined multiple times in class TestXml.
../classes.h:108: Warning: The property 'collection' is defined multiple times in class TestXml.
../classes.h:108: Warning: The property 'object' is defined multiple times in class TestXml.

Snippet of gcc class Parent example intermediate code after preprocessing and beautifying (compile with -E option)

#
7 "../classes.h"
class Parent: public QSerializer
{
	#
	8 "../classes.h"
	3 4
	public: static
	const QMetaObject staticMetaObject;
	void qt_check_for_QGADGET_macro();
	typedef void QtGadgetHelper;
	private: #8 "../classes.h"#
	pragma GCC diagnostic push# 8 "../classes.h"

	# 8 "../classes.h"#
	pragma GCC diagnostic ignored "-Wattributes"#
	8 "../classes.h"
	__attribute__((visibility("hidden"))) static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);#
	8 "../classes.h"#
	pragma GCC diagnostic pop# 8 "../classes.h"

	# 9 "../classes.h"
	virtual
	const QMetaObject* metaObject() const
	{
		return &this->staticMetaObject;
	}

	public:
		Parent() {}

	Parent(int age, const QString &name, bool isMale): age(age),
		name(name),
		male(isMale) {}

	public: int age = int();
	private: QJsonValue get_json_age() const
	{
		QJsonValue val = QJsonValue::fromVariant(QVariant(age));
		return val;
	}

	void set_json_age(const QJsonValue &varname)
	{
		age = varname.toVariant().value<int> ();
	}

	private: QDomNode get_xml_age() const
	{
		QDomDocument doc;
		QString strname = "age";
		QDomElement element = doc.createElement(strname);
		QDomText valueOfProp = doc.createTextNode(QVariant(age).toString());
		element.appendChild(valueOfProp);
		doc.appendChild(element);
		return QDomNode(element);
	}

	void set_xml_age(const QDomNode &node)
	{
		if (!node.isNull() && node.isElement())
		{
			QDomElement domElement = node.toElement();
			if (domElement.tagName() == "age") age = QVariant(domElement.text()).value<int> ();
		}
	}

	public: QString name = QString();
	private: QJsonValue get_json_name() const
	{
		QJsonValue val = QJsonValue::fromVariant(QVariant(name));
		return val;
	}

	void set_json_name(const QJsonValue &varname)
	{
		name = varname.toVariant().value<QString> ();
	}

	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(element);
	}

	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<QString> ();
		}
	}

	public: bool male = bool();
	private: QJsonValue get_json_male() const
	{
		QJsonValue val = QJsonValue::fromVariant(QVariant(male));
		return val;
	}

	void set_json_male(const QJsonValue &varname)
	{
		male = varname.toVariant().value<bool> ();
	}

	private: QDomNode get_xml_male() const
	{
		QDomDocument doc;
		QString strname = "male";
		QDomElement element = doc.createElement(strname);
		QDomText valueOfProp = doc.createTextNode(QVariant(male).toString());
		element.appendChild(valueOfProp);
		doc.appendChild(element);
		return QDomNode(element);
	}

	void set_xml_male(const QDomNode &node)
	{
		if (!node.isNull() && node.isElement())
		{
			QDomElement domElement = node.toElement();
			if (domElement.tagName() == "male") male = QVariant(domElement.text()).value<bool> ();
		}
	}
};

Support for Enums

Hi,
would it be possible to add support for enumerates?
it would be great if you could choose whether to use the number value or the string for serialization/deserialization.

Thanks

In this case, it is not possible to get.

hello thanks a lot for help
In my case, I tested it, and it is confirmed that the file is written normally.

But in the process of getting the value with Get, I got an abnormal result.

class cModelCommon : public cSerializer
{
public:
	        Q_GADGET
		QS_SERIALIZABLE

		QS_FIELD(QString, strMethodName)				//	메소드 이름 
		QS_FIELD(QString, strMemo)						//	메모
		QS_FIELD(int, nTime)							//	횟수
		QS_FIELD(int, nUnit)							//	단위
		QS_FIELD(QDateTime, CreationTime)				//	생성 시간
		QS_COLLECTION(QVector, int, vWaveLength)		//	파장
		QS_COLLECTION(QVector, int, vCelltype)			//	셀 타입 Ex) B,1,2..., S(Single)
};

class cModelQuantitation : public cModelCommon
{
	Q_GADGET
		QS_SERIALIZABLE
		QS_OBJECT(cModelQuantitation_MeasureData,	cMeasureData)	 //	측정결과
		QS_OBJECT(cModelStandardCurve,				cStandardCurve)	 //	리포트옵션
		QS_OBJECT(cReportOption,					cReportopt)		 //	리포트옵션
};

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, cMeasureData)	//	측정결과
		QS_OBJECT(cReportOption, cReportopt)						//	리포트옵션
};
class cReportOption : public cSerializer
{
	Q_GADGET
		QS_SERIALIZABLE

		QS_FIELD(bool, bShowTitle)						//	측정 타이틀
		QS_FIELD(bool, bShowDeviceInfo)					//	장비 정보
		QS_FIELD(bool, bShowInfo)						//	상세 정보
		QS_FIELD(bool, bShowData)						//	측정 데이터 
		QS_FIELD(bool, bShowChart)						//	차트 정보
};

This is the case with the class relationship diagram, what should I do to properly handle this case?

Fields of cModelCommon class are imported normally.
However, the class object of cModelQuantitation gets the initial value.

nan parsing problem

When converting nan QS_FIELD(double,field_name) to json, it writes down 'null'(default QVariant behavior). At the same time, pasrsing 'null' as double, 'includes' variable sets to false, and QS_FIELD(double,field_name) retains zero.

CMake + vcpkg

Как насчёт добавления поддержки CMake? Так как Qt6 будет переходить именно на этот генератор сборочных систем. Плюс CMake сейчас практически стандарт.

А до кучи можно ещё и вкинуть либу в vcpkg, ибо любые библиотеки нужны C++ сообществу.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.