Git Product home page Git Product logo

qtjsonserializer's Introduction

QtJsonSerializer

A library to perform generic seralization and deserialization of QObjects from and to JSON and CBOR.

With this small library, you are able to serialize any C++ datatype to JSON or CBOR and back. This is done with help of Qt's meta system.

Github Actions status Codacy Badge AUR

The library was recently update to 4.0.0. Have a look at the Porting section to learn how to migrate your project from 3.* to 4.0.0. Don't be afraid, as for most existing projects, only class names will have changed.

Features

  • Serialize QObjects, Q_GADGETS, lists, maps, etc. to JSON/CBOR, in a generic matter
  • ... and of course deserialize JSON/CBOR back as well
  • De/serialize any QVariant - as long as it contains only basic types or one of the above
    • Works even with QJsonValue/Array/Object as properties
  • Serializes Q_PROPERTY elements
  • Enum de/serialization as integer or as string
  • Deserialization: Additional JSON/CBOR-values will be stored as dynamic properties for QObjects
  • Supports polymorphism
  • Fully Unit-Tested
  • Thread-Safe
  • Easily extensible

Download/Installation

There are multiple ways to install the Qt module, sorted by preference:

  1. Package Managers: The library is available via:
  2. Simply add my repository to your Qt MaintenanceTool (Image-based How-To here: Add custom repository):
    1. Start the MaintenanceTool from the commandline using /path/to/MaintenanceTool --addRepository <url> with one of the following urls (Alternatively you can add it via the GUI, as stated in the previously linked GUI):
    2. A new entry appears under all supported Qt Versions (e.g. Qt > Qt 5.13 > Skycoder42 Qt modules)
    3. You can install either all of my modules, or select the one you need: Qt JsonSerializer
    4. Continue the setup and thats it! you can now use the module for all of your installed Kits for that Qt
  3. Download the compiled modules from the release page. Note: You will have to add the correct ones yourself and may need to adjust some paths to fit your installation!
  4. Build it yourself! Note: This requires perl to be installed. If you don't have/need cmake, you can ignore the related warnings. To automatically build and install to your Qt installation, perform the following steps:
    • Download the sources. Either use git clone or download from the releases. If you choose the second option, you have to manually create a folder named .git in the projects root directory, otherwise the build will fail.
    • qmake
    • make (If you want the tests/examples/etc. run make all)
    • Optional steps:
      • make doxygen to generate the documentation
      • make -j1 run-tests to build and run all tests
    • make install

Building without converter registration

By default, a bunch of list, map, etc. converters are registered for standard Qt types via the qtJsonSerializerRegisterTypes method. This however needs many generated functions and will increase the size of the generated binary drasticly. If you don't need those converters, run qmake CONFIG+=no_register_json_converters instead of a parameterless qmake. The mentioned function will then be generated as noop method and no converters are registerd.

Please be aware that in this mode it is not possible to serialize e.g. QList<int> unless you manually register the corresponding converters via QtJsonSerializer::JsonSerializer::registerListConverters<int>();!

Usage

The serializer is provided as a Qt module. Thus, all you have to do is install the module, and then, in your project, add QT += jsonserializer to your .pro file! The following chapters show an example and explain a few important details regarding the functionality and limits of the implementation.

Example

Both serialization and desertialization are rather simple. Create an object, and then use the serializer as follows:

The following is an example for a serializable object. Note: The usage of MEMBER Properties is not required, and simply done to make this example more readable.

class TestObject : public QObject
{
	Q_OBJECT

	Q_PROPERTY(QString stringProperty MEMBER stringProperty)
	Q_PROPERTY(QList<int> simpleList MEMBER simpleList)
	Q_PROPERTY(QMap<QString, double> simpleMap MEMBER simpleMap);  // add the semicolon or use a typedef to surpress most errors of the clang code model
	Q_PROPERTY(TestObject* childObject MEMBER childObject)

public:
	Q_INVOKABLE TestObject(QObject *parent = nullptr);

	QString stringProperty;
	QList<int> simpleList;
	QMap<QString, double> simpleMap;
	TestObject* childObject;
}

You can serialize (and deserialize) the object with:

auto serializer = new QJsonSerializer(this);

try {
	//serialize
	auto object = new TestObject();
	object->stringProperty = "test";
	object->simpleList = {1, 2, 3};
	object->simpleMap = {
		{"pi", 3.14},
		{"e", 2.71}
	};
	object->childObject = new TestObject(object);
	auto json = serializer->serialize(object);
	qDebug() << json;
	delete object;

	//deserialize
	object = serializer->deserialize<TestObject>(json);//optional: specify the parent
	qDebug() << object->stringProperty
			 << object->simpleList
			 << object->simpleMap
			 << object->childObject;
	delete object;
} catch(QJsonSerializerException &e) {
	qDebug() << e.what();
}

For the serialization, the created json would look like this:

{
	"stringProperty": "test",
	"simpleList": [1, 2, 3],
	"simpleMap": {
		"pi": 3.14,
		"e": 2.71
	},
	"childObject": {
		"stringProperty": "",
		"simpleList": [],
		"simpleMap": {},
		"childObject": null
	}
}

Important Usage Hints

In order for the serializer to properly work, there are a few things you have to know and do:

  1. Only Q_PROPERTY properties of objects/gadgets will be serialized, and of those only properties that are marked to be stored (see The Property System, STORED attribute)
  2. For the deserialization of QObjects, they need an invokable constructor, that takes only a parent: Q_INVOKABLE MyClass(QObject*);
  3. The following types are explicitly supported:
    • QObject* and deriving classes
    • Classes/structs marked with Q_GADGET (as value or plain pointer only!)
    • QList<T>, QLinkedList<T>, QVector<T>, QStack<T>, QQueue<T>, QSet<T>, with T beeing any type that is serializable as well
    • QMap<QString, T>, QHash<QString, T>, QMultiMap<QString, T>, QMultiHash<QString, T>, with T beeing any type that is serializable as well (string as key type is required)
    • Simple types, that are supported by QJsonValue (See QJsonValue::fromVariant and QJsonValue::toVariant)
    • Q_ENUM and Q_FLAG types, as integer or as string
      • The string de/serialization of Q_ENUM and Q_FLAG types only works if used as a Q_PROPERTY. Integer will always work.
    • QJson... types
    • QPair<T1, T2> and std::pair<T1, T2>, of any types that are serializable as well
    • std::tuple<TArgs...>, of any types that are serializable as well
    • std::optional<T>, of any type that is serializable as well
    • std::variant<TArgs...>, of any types that are serializable as well
    • std::chrono::*, for the basic times (hours, minutes, seconds, milliseconds, microseconds, nanoseconds)
    • Standard QtCore types (QByteArray, QUrl, QVersionNumber, QUuid, QPoint, QSize, QLine, QRect, QLocale, QRegularExpression, ...)
      • QByteArray is represented by a base64 encoded string
    • Any type you add yourself by extending the serializer (See QJsonTypeConverter documentation)
  4. While simple types (i.e. QList<int>) are supported out of the box, for custom types (like QList<TestObject*>) you will have to register converters. This goes for
    • List-, Set- and Map-Types: use SerializerBase::registerBasicConverters<T>()
    • List-Types only: use SerializerBase::registerListConverters<T>()
    • Set-Types only: use SerializerBase::registerSetConverters<T>()
    • Map-Types only: use SerializerBase::registerMapConverters<T>()
      • Maps and hashes can be registered seperately using a template parameter, if you only need one of those
    • QPair and std::pair: use SerializerBase::registerPairConverters<T1, T2>()
    • std::tuple: use SerializerBase::registerTupleConverters<TArgs...>()
    • std::optional: use SerializerBase::registerOptionalConverters<T>()
    • std::variant: use SerializerBase::registerVariantConverters<TArgs...>()
    • QSharedPointer/QPointer: use SerializerBase::registerPointerConverters<T>()
  5. Polymorphic QObjects are supported. This is done by the serializer via adding a special @@class json property. To make a class polymorphic you can:
    • Add Q_JSON_POLYMORPHIC(true) (or Q_CLASSINFO("polymorphic", "true")) to its definition
    • Globally force polyphormism (See QJsonSerializer::polymorphing in the doc)
    • Set a dynamic property: setProperty("__qt_json_serializer_polymorphic", true);
  6. By default, the objectName property of QObjects is not serialized (See keepObjectName)
  7. By default, the JSON null can only be converted to QObjects. For other types the conversion fails (See allowDefaultNull)

Support for alternative Containers

While the default Qt containers, like QList, QVector and QMap are all supported by default, custom containers need to be registered. For this, two steps need to happen:

  • For sequential containers:
    1. Register the container via Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE
    2. Make it available for a certain type via QtJsonSerializer::SequentialWriter::registerWriter<Container, Type>()
  • For associative containers:
    1. Register the container via Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE
    2. Make it available for a certain type via QtJsonSerializer::AssociativeWriter::registerWriter<Container, Key, Value>()

Documentation

The documentation is available on github pages. It was created using doxygen. The HTML-documentation and Qt-Help files are shipped together with the module for both the custom repository and the package on the release page. Please note that doxygen docs do not perfectly integrate with QtCreator/QtAssistant.

Porting

Most changes to the library have been of additive nature. The following list summarizes the most important changes:

  • Support for CBOR de/serialization
  • Support for generic sequential and associative containers
  • Improved type safety via extraxtors
  • More converters (including bitarrays, smart pointers and enums)
  • All types have been renamed and moved into the QtJsonSerializer namespace

The next sections will talk about specific changes and how to adjust your project. Also, if you have any questions or need help porting your project, I am always happy to help. Just create a new Issue asking for help, and it shall be given.

Rename refactoring

One big part of the 4.0.0 release was to move all types into a namespace and get rid of the QJson prefix. The following table shows how types have been renamed. If you do not want to change all usages in your code, simply use using declarations for the types, i.e. using QJsonSerializer = QtJsonSerializer::JsonSerializer;.

Old name New name
QJsonSerializerException QtJsonSerializer::Exception
QJsonDeserializationException QtJsonSerializer::DeserializationException
QJsonSerializationException QtJsonSerializer::SerializationException
QJsonSerializer QtJsonSerializer::JsonSerializer (split into that class and the base class QtJsonSerializer::SerializerBase)
QJsonTypeConverter QtJsonSerializer::TypeConverter

Changes in type registrations

With the new system, typedefs are no longer a problem, as now, an advanced type registration system is used to get types instead of parsing class names. Thus, all related methods have been removed. Furthermore, the old system of converting various datatypes from and to a non-generic QVariant representation via QMetaType has been superseeded by the QtJsonSerializer::TypeExtracor system. For most usecases this changes nothing, as the QtJsonSerializer::SerializerBase::register* methods still exist. However, if you made use of the old system in custom converters, you should consider migrating to using either the QtJsonSerializer::MetaWriter mechanism for containers, or the QtJsonSerializer::TypeExtracor for other types. Check the documentation on how to use these classes.

Support for more containers

One additional advantage of the new system is, that now theoretically any sequential or associative container can be supported by the serializer without the need of a custom converter. Alls that is needed is a simple registration of a custom container class within the QtJsonSerializer::MetaWriter classes as well as the type declaration (See Support for alternative Containers). The following shows a simple example for std::vector

Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::vector)
// ...
QtJsonSerializer::SequentialWriter::registerWriter<std::vector, int>();
QtJsonSerializer::SequentialWriter::registerWriter<std::vector, double>();
QtJsonSerializer::SequentialWriter::registerWriter<std::vector, QString>();
// ...

CBOR support

The biggest feature however is support for de/serialization of CBOR data. Usage is the same as for JSON, simply use QtJsonSerializer::CborSerializer instead of the QtJsonSerializer::JsonSerializer class. Nothing more to say here - simply try it out!

Changes for TypeConverters

If you previously had your own QJsonTypeConverter (now called QtJsonSerializer::TypeConverter), the changes are slightly more complex. The primary change was, that all these converter now operate on CBOR data, not JSON, as CBOR can be easily converted to JSON, but not the other way around. Check the QtJsonSerializer::TypeConverter documentation for more details on how to use these new converters.

qtjsonserializer's People

Contributors

felix-barz-brickmakers avatar lainwir3d avatar skycoder42 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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

qtjsonserializer's Issues

Runtime termination when serializing QList<std::complex<double>>

I have a class definition as followed (In shortly):

class Model : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QList<std::complex<double>> Chi MEMBER Chi)

protected:

    QList <std::complex<double>> Chi;
}

And I declared the metatype as you stated:
Q_DECLARE_METATYPE(std::complex<double>)
In usage, I register the list as you suggested;
QJsonSerializer::registerListConverters<std::complex<double>>();

And when It comes to serilaze it throws exception and terminates:

terminate called after throwing an instance of 'QJsonSerializationException'
  what():  what: Failed to serialize with error: Failed to convert type std::complex<double> to a JSON representation
Property Trace:
        Chi (Type: QList<std::complex<double> >)
        [0] (Type: std::complex<double>)

This application has requested the Runtime to terminate it in an unusual way.

I know it is a matter of conversion thing and It would be lifesaver resolving this.

Regards

Can not serialize enum properties

Hi I'm using Qt version 5.10.0.
I get this error when serializing this class :
`class Spectra : public QObject
{
Q_OBJECT
Q_ENUM(SpectrumType)
Q_ENUM(SpectrumPolarization)
Q_PROPERTY(double incidenceAngle MEMBER incidenceAngle)
Q_PROPERTY(SpectrumType type MEMBER type)
Q_PROPERTY(SpectrumPolarization polarization MEMBER polarization)

public:
Q_INVOKABLE Spectra(QObject *parent = nullptr) : QObject(parent)
{
type = ST_Reflectance;
incidenceAngle = 0.0;
polarization = SP_Unpolarized;
}

~Spectra(){}

double incidenceAngle;
SpectrumType type;
SpectrumPolarization polarization;

};

Q_DECLARE_METATYPE(Spectra *) `

At runtime it says ;
QMetaProperty::read: Unable to handle unregistered datatype 'SpectrumType' for property 'Spectra::type'
QMetaProperty::read: Unable to handle unregistered datatype 'SpectrumPolarization' for property 'Spectra::polarization'

Then serializes the object as depicted below
{ "spectraList": [ { "incidenceAngle": 0, "polarization": null, "type": null } ] }
To register datatypes I added required meta type declarations;

Q_DECLARE_METATYPE(SpectrumType) Q_DECLARE_METATYPE(SpectrumPolarization)
This time QtJsonserializer throws exeption and crashes;
terminate called after throwing an instance of 'QJsonSerializationException' what(): what: Failed to serialize with error: Failed to convert type SpectrumType to a JSON representation Property Trace: spectraList (Type: QList<Spectra*>) [0] (Type: Spectra*) type (Type: SpectrumType)

Invalid line endings in cpp files under .reggen

Hello! I've got the following error for generated qjsonconverterreg_*.cpp files: warning C4335: Mac file format detected: please convert the source file to either DOS or UNIX format.
I suppose that wrong line endings prevent me from debugging within Visual Studio 2017.

Build QtJsonSerializer as static lib on Windows

Hey Felix, I'm trying to build the module as a static lib on Windows to link with my executable so I don't have to deploy the .dll. I've used the Qt MaintenanceTool as per your instructions to add the module to my Qt source tree as user defined repo. I rebuilt Qt (5.11.2) statically from source using configure and jom. It looks the QtJsonSerializer has not been built along with Qt base and the other default Qt modules, I don't see the QtJsonSerializer lib.

Do you know the configure switch or procedure to build your module as part of a QT from source build under Windows?

Alternatively, how would I just add the module sources to my Qt App project and have it built along with the app and linked in statically?

A third way I can think of would be to separately build just QtSerializer statically in one step and add the .lib to my App .pro file. Attempting this using qmake and jom yield path issues for files not being compiled/generated (LINK : fatal error LNK1181: Input ".obj\release\qjsonconverterreg_0.obj" could not be opened).

I understand you have pre-built binaries for various platforms on your release page - these are dynamic libs however and need the runtime Dll.

Any help or hint is appreciated. Thanks!

  • Ben

GCC 4.7.2 build errors

Hello! I have to use old GCC 4.7.2. Building your project leads to the following errors:
In file included from qjsonserializerexception.cpp:1:0: qjsonserializerexception.h:12:31: error: looser throw specifier for ‘virtual QJsonSerializerException::~QJsonSerializerException()’ In file included from /usr/lib/Qt5.9/include/QtCore/QtCore:56:0, from ../../include/QtJsonSerializer/QtJsonSerializerDepends:3: /usr/lib/Qt5.9/include/QtCore/qexception.h:62:5: error: overriding ‘virtual QException::~QException() noexcept (true)’ make[2]: *** [.obj/qjsonserializerexception.o] Error 1 make[2]: Leaving directory /home/user/QtJsonSerializer/src/jsonserializer'
make[1]: *** [sub-jsonserializer-make_first-ordered] Error 2
make[1]: Leaving directory /home/user/QtJsonSerializer/src' make: *** [sub-src-make_first] Error 2

Tell me please, what is the workaround?

Failed to build with Qt 5.11.2

Hello! I can't build your library using Qt 5.11.2 in Windows (MS VS 2017). But Qt 5.12.1 works fine. At least, please, add minimal supported Qt version.

Creating library ....\lib\Qt5JsonSerializerd.lib and object ....\lib\Qt5JsonSerializerd.exp
qjsonconverterreg_22.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) unsigned int __cdecl qHash(class QJsonValue const &,unsigned int)" (_imp?qHash@@YAIAEBVQJsonValue@@i@Z) referenced in function "private: struct QHashNode<class QJsonValue,struct QHashDummyValue> * * __cdecl QHash<class QJsonValue,struct QHashDummyValue>::findNode(class QJsonValue const &,unsigned int *)const " (?findNode@?$QHash@VQJsonValue@@UQHashDummyValue@@@@AEBAPEAPEAU?$QHashNode@VQJsonValue@@UQHashDummyValue@@@@AEBVQJsonValue@@peai@Z)
qjsonconverterreg_23.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) unsigned int __cdecl qHash(class QJsonObject const &,unsigned int)" (_imp?qHash@@YAIAEBVQJsonObject@@i@Z) referenced in function "private: struct QHashNode<class QJsonObject,struct QHashDummyValue> * * __cdecl QHash<class QJsonObject,struct QHashDummyValue>::findNode(class QJsonObject const &,unsigned int *)const " (?findNode@?$QHash@VQJsonObject@@UQHashDummyValue@@@@AEBAPEAPEAU?$QHashNode@VQJsonObject@@UQHashDummyValue@@@@AEBVQJsonObject@@peai@Z)
qjsonconverterreg_24.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) unsigned int __cdecl qHash(class QJsonArray const &,unsigned int)" (_imp?qHash@@YAIAEBVQJsonArray@@i@Z) referenced in function "private: struct QHashNode<class QJsonArray,struct QHashDummyValue> * * __cdecl QHash<class QJsonArray,struct QHashDummyValue>::findNode(class QJsonArray const &,unsigned int *)const " (?findNode@?$QHash@VQJsonArray@@UQHashDummyValue@@@@AEBAPEAPEAU?$QHashNode@VQJsonArray@@UQHashDummyValue@@@@AEBVQJsonArray@@peai@Z)
....\lib\Qt5JsonSerializerd.dll : fatal error LNK1120: 3 unresolved externals
NMAKE : fatal error U1077: '"D:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.16.27023\bin\HostX64\x64\link.EXE"' : return code '0x460'
Stop.

(De-)Serializing outer enums

Let's assume that we have an old C enum wrapped inside of the Q_GADGET struct:

struct MyEnumWrapper
{
 Q_GADGET
 //re-open public visibility after Q_GADGET
 public:
 enum Enum
 {
  unknown,
  one,
  two,
  three
 };
Q_ENUM(Enum)
};

Now we have another Q_GADGET struct which must be serialized. It contains field MyEnumWrapper::Enum myEnumField; How should Q_PROPERTY and other stuff like getter be organized for QtJsonSerializer? I mean that I'd like to see stringified enum values. I am aware about setEnumAsString(true);.

CopperSpice support

Hello! I have to switch to bare metal ARM (Xilinx Zynq-7000).
I have plenty of PODs (Q_GADGET's) for JSON serialization.
I cannot use Qt for MCUs. Is it technically possible to adapt QtJsonSerializer for CopperSpice support? I mean using reduced version of CsCore and QtJsonSerializer for bare metal. Surely, I don't ask you to do this task, just want to know whether it requires a lot of work or is totally impossible.
P.S. Bare metal doesn't imply a memory size, it only means that there's no full-blown operating system.

Using QtJsonSerializer as a static library

Hello! I have a static version of Qt 5.12 (Windows). QtJsonSerializer was installed as a static lib. But the problem is linked with Q_JSONSERIALIZER_EXPORT define. It is redundant for static version. How this can be fixed? I prefer CMake (Qt developers even dropped qbs, qmake will be obsolete too in the far future, the will concentrate on CMake). BTW, I use QtJsonSerializer CMake module.

Runtime exception occurred in sample.

QT version: 5.14.1
QtJsonSerializer install way: Download the compiled modules from the release page.
System: windows 10
Build setting: Qt_5_14_1_MSVC2017_64bit-Debug

No changes have been made to the sample code except to add 'CONFIG += c++17 ' to 'Sample.pro'.

Exceptions are shown in the figure below:

image

image

Best practices for registering custom types for QtJsonSerializer

Hello! What should I do if I have multiple custom embedded types?
For example, matryoshka;

Gadget_A {
    QList<B> b_list;
};
//...
Gadget_B {
    QList<C> c_list;
};
//...
Gadget_C: {
    QString name;
};

What are the tricks for tracking such types? I mean QJsonSerializer::registerListConverters() usage. For example, if we use Q_DECLARE_METATYPE, then we put it after class declaration,
Placing QJsonSerializer::registerListConverters() in main.cpp is more error-prone.

Poor performance for array of PODs with simple properties

Hello! I have 10000 PODs. Each POD contains primitive properties, so CBOR<->QVariant conversion can be done without iterating converter "store" (more than 20 checks a-la canConvert are done before switching to default conversion). So, using helper()->serializeSubtype is expensive for primitive types. Is it possible to improve performance if we deal with simple types? I don't want to subclass converter in order to speed up conversion.

QVector support

If the struct (Q_GADGETed) contains QVector, what can be done in order to make your library work? I've read about registering QList's, but QVector is also very popular data structure. It is considered as a default choice in Qt5 docs (older Qt4 docs advertized QList).

Deserialize into existing object

I would like to update all or selected properties of an existing object. Is it possible to do it with QtJsonSerializer?

Right now I am writing such de-serialization functions myself, but it is a bit tedious.

head of line cannot run sample application

I am using Qt 5.15.0. I followed the steps in the readme for building the library and sample code from scratch. everything seems to build fine but when I run the sample application I get the follow.
error while loading shared libraries: libQt5JsonSerializer.so.4: cannot open shared object file: No such file or directory
Now i double checked the make files for sample which pointed to the correct path for the library. So I don't know what the issue could be. Any help would be much appreciated. attached is my console ouput for two commands. Also should my bin folder include anything? cause at the moment its empty
makeall_output.txt
makeinstall_output.txt

Error "too many arguments provided to function-like macro invocation" using QMap

I get this error
"too many arguments provided to function-like macro invocation"

using QMap as Property:
Q_PROPERTY( QMap<QString, myClass*> mylist MEMBER mylist )

I did a lot of investigating in the net and the result is, that Q_PROPERTY is a macro of Q_OBJECT, which doesn't support variadic templates, so the comma necessary to define the QMap within Q_PROPERTY macro is not supported.

The only way to remove the error is to bundle the QMap definition in a Typedef, but seems to be not supported in QJsonSerializer library.

In the examples there is no example for using QMap; maybe I used it wrong.

Could you add a example how to use QMap with custom class to serialize and deserialize?

registerSetConverters results in build time error no matching function to call qHash(...

registerSetConverters results in build time error no matching function to call qHash(...
my class

class simpleGadget
{
    Q_GADGET
    Q_PROPERTY(int id MEMBER id)
    Q_PROPERTY(bool flag MEMBER flag);
    Q_PROPERTY(float fValue MEMBER fValue);
    Q_PROPERTY(double dValue MEMBER dValue);
    Q_PROPERTY(long lValue MEMBER lValue);
    Q_PROPERTY(QString sValue MEMBER sValue);
    Q_PROPERTY(QList<int> iValues MEMBER iValues);
    Q_PROPERTY(QByteArray byteValue MEMBER byteValue);
public:
    simpleGadget(){}
    ~simpleGadget(){}
    int id = -1;
    bool flag = true;
    float fValue = 3.14;
    double dValue = 33.5555555;
    long lValue = 100000;
    QByteArray byteValue = "1234567A";
    QString sValue = "Hello World";
    QList<int> iValues = {1,2,3};
    QByteArray expectedJson = "{\"byteValue\":\"MTIzNDU2N0E=\",\"dValue\":33.5555555,\"fValue\":3.140000104904175,\"flag\":true,\"iValues\":[1,2,3],\"id\":-1,\"lValue\":\"100000\",\"sValue\":\"Hello World\"}";
    bool operator==(const simpleGadget& newValue) const
    {
        return (id == newValue.id &&
                flag == newValue.flag &&
                fValue == newValue.fValue &&
                dValue == newValue.dValue &&
                lValue == newValue.lValue &&
                sValue == newValue.sValue &&
                iValues == newValue.iValues &&
                byteValue == newValue.byteValue);
    }

    bool operator!=(const simpleGadget& newValue) const
    {
        return !(*this == newValue);
    }
};
Q_DECLARE_METATYPE(simpleGadget)

How to deserialize derived classes that use none-default constructors

Hello there,
I was trying to deserialize some polymorphic classes which use none-default constructors by creating my own QJsonTypeConverter with the help of discussion about it in issue #22.
let's say we have class Base and class Derived.
I faced a problem with the canConvert() function.
when I want to deserialize the Derived class canConvert() is called with the metaTypeId of Base * instead of Derived *.
Am I doing something wrong?
How can I solve that problem?

What to do to reduce compile time and binary size used for registering unneeded type converters

Hello there.
I'm currently using version 3.3.1-3 and I have to keep using that version because I have to use Qt 5.12.4.
The problem as mentioned in the title is that I need to compact my final binary file and also reduce compile time but registering all the converters is taking a lot of resources.
Can you show me a clean way to remove those converters and register only needed ones?

Thanks in advance.

Mac build "make" step giving .reggen errors. Any advice?

When I call make on 4.0.3 I'm getting this. I've built the last several versions and have never had this problem.

/Qt_Commercial/5.14.1/QtJsonSerializer-4.0.3/src/jsonserializer/qjsonreggen.py /Qt_Commercial/5.14.1/QtJsonSerializer-4.0.3/src/jsonserializer/.reggen/qjsonconverterreg_bool.cpp bool
env: python3: No such file or directory
make[2]: *** [/Qt_Commercial/5.14.1/QtJsonSerializer-4.0.3/src/jsonserializer/.reggen/qjsonconverterreg_bool.cpp] Error 127
make[1]: *** [sub-jsonserializer-make_first] Error 2
make: *** [sub-src-make_first] Error 2

Ignoring STORED attribute mode

Hello! I think that sometimes it's helpful to have an ability to serialize properties even with STORED=false.
For example, we save all properties for output in debug log and subset of properties with STORED=true for REST service response.

How to register a custom complex type

in my program, i need some kind of type, like QMap<QString, QList<SaleProperty*>>
but no matter what i tried, it always crash

Here is whate i tried:
qRegisterMetaType<QMap<QString, QList<SaleProperty*>>>("QMap<QString, QList<SaleProperty*>>");
qRegisterMetaType<QMap<QString, QStringList>>("QMap<QString, QStringList>");
qRegisterMetaType<QMap<QString, QList>>("QMap<QString, QList>");
QJsonSerializer::registerAllConverters<QList>();
QJsonSerializer::registerMapConverters<QList<SaleProperty*>>();
QJsonSerializer::registerListConverters<SaleProperty*>();

I would be very grateful if you can provide some help.

Create references to existing object , not duplicates

Assuming I have some code like this
QList<QSharedPointer> aList;
QSharedPointer tmp(new SampleObject());
aList.append(tmp);
aList.append(tmp);
auto jsonarray = serializer.serialize(aList);
qDebug() << "\nSerialize a QList now:";
qDebug() << JSON_PRINT(jsonarray);

Then the generated JSON has duplicates of the object. Clearly this will not restored as intended.
The application code could use "names" or some other "ids" to prevent duplication as a workaround.
Just wondering if this has been thought of/dealt with by others.

Serialize QSet<MyEnum> as QSet<int>

Hello! I'd like to serialize Q_GADGET member QSet<MyEnum> enumSet as a set of int's. But serialization converts it to string, though I didn't called setEnumAsString(true).

Custom Containers & Inheritance

Greetings,

first off, thank you very much for this wonderful library, it makes JSON serialization much easier to deal with. Thanks a lot!

However, how do you declare a class that inherit a container with the type already given? I have the current code, which works but this produce an ugly QJsonObject rather than a nice and simple QJsonArray like I would want it to be or is this simply not possible? Thank you very much!

foo.hpp

class Foobar
{
    Q_GADGET

    Q_PROPERTY(QString name MEMBER m_name)

public:
    QString m_name;
};
Q_DECLARE_METATYPE(Foobar)

class FoobarList : public QList<Foobar>
{
    Q_GADGET

    Q_PROPERTY(QJsonArray a READ getFoobarList WRITE setFoobarList)

public:
    static void registerMetaType()
    {
        qRegisterMetaType<FoobarList>();
        QtJsonSerializer::JsonSerializer::registerListConverters<FoobarList>();
    }

    FoobarList(const QList<Foobar> &a = QList<Foobar>())
        : QList(a)
    {}
    QJsonArray getFoobarList() const
    {
        /** do something **/
        
        return QJsonArray();
    }
    void setFoobarList(const QJsonArray &a)
    {
        /** do something **/
    }
};
Q_DECLARE_METATYPE(FoobarList)
Q_DECLARE_TYPEINFO(FoobarList, Q_MOVABLE_TYPE);

foo.cpp

namespace
{
    void registerMetaType()
    {
        FoobarList::registerMetaType();
    }
} // namespace
Q_COREAPP_STARTUP_FUNCTION(registerMetaType)

Expected output:

[
    "Foo0000",
    "Foo0001",
    "Foo0002"
]

Current output:

[
    {
        "name": "Foo0000"
    },
    {
        "name": "Foo0001"
    },
    {
          "name": "Foo0002"
    }
]

Sample: SerializationException (Unable to determine typeid of meta enum SampleObject::SuperFlags)

Hi,
I compiled the QtJsonSerializer, and installed.
Then try to run sample, the only change was to Sample.pro where I added CONFIG += c++1z
If I run the Sample application from the command line I get the following output:

Serializing SampleGadget:
{
    "base": [
        42,
        13
    ],
    "rawData": {
        "someData": false
    }
}


And deserializing data back:
base: QPoint(42,13)
rawData: {
    "someData": false
}


Now the test object, with the previous gadget as child:
terminate called after throwing an instance of 'QtJsonSerializer::SerializationException'
  what():  what: Failed to serialize with error: Unable to determine typeid of meta enum SampleObject::SuperFlags
Property Trace:
	flags (Type: SuperFlags)
Annullato (core dump creato)

System is Ubuntu 16.04 with:
Qt v5.14.2
g++ v7.5.0

Q_GADGET and QVariantList

Hello!
I am trying to serialize Q_GADGET struct (My_gadget). It contains QVariantList children.
These children are QVariant values which encapsulate My_gadget. The corresponding property is not serialized (it's a pity). If i change to QVariant child, then it fails too. What is the workaround?
In real project QVariantList will contain other Q_GADGETs too.

P.S. AFAIK, CBOR is used internally in this serializer even if I need JSON. Q_GADGET struct fails to convert to QCBorValue via QVariant wrapper, because QVariant::toString() returns empty string.

Deserialization QPair within QVariant

Hello!
I have QVariant field1 within Q_GADGET (JSON serialization). This field contain QPair<int,int> (for example). field1 can contain some gadgets, each one is linked with Gadget_type enum. Gadget contains Gadget_type field2 (enum which depicts actual data type).
I've added all typical metatype registration stuff, including QMetaType::registerConverter. The result field value is in quotes: "field1":"[1,2]". The problem is linked with deserialization exception:

Failed to deserialize with error: Failed to convert deserialized variant of type QString to property type QVariant. Make shure to register converters with the QJsonSerializer::register* methods.

Question On Usage of the library.

I would like to serialise QList<TestObject *> * and QHash<QString,TestObject *> * and i am having a bit of a hard time figuring out how to do it. More specifically i am trying to serialise lists and hashes that are members of a class but have been allocated on the heap instead of the stack. I would appreciate your help.

Awesome library by the way!!!

QHash<int, QString> workaround

Hello! Is it reasonable to represent QHash<int, QString> field as QVariantHash property (using getter/setter fo conversion)?

Using multiple instances in Qt subdir

Hello! I have to use 3.x and 4.x versions of QtJsonSerializer in different projects.
The problem is that Qt subdir gcc_64/include/QtJsonSerializer/ contains headers which are different for 3.x and 4.x. Why don't these specific headers stay in 4.x and 3.x subdirs? For example, jsonserializer.h.

Q_PROPERTY with type std::optional

Hi.
Is it right that one can use std::optional as Q_PROPERTY type, e.g. like following (since 3.4)?

Q_DECLARE_METATYPE(std::optional<int>)
...
QJsonSerializer::registerOptionalConverters<int>();
...

class Test : public QObject {
    Q_OBJECT

    Q_PROPERTY(std::optional<int> type READ type WRITE setType NOTIFY typeChanged)

signals:
    void typeChanged();

public:
    void setType(std::optional<int> type);
    std::optional<int> type() const;

private:
    std::optional<int> m_type;
};

Thank you.

Embedding de-(serialization) into Q_GADGET

Hello! I'd like my Q_GADGETS to convert to JSON and vice versa without external calls to QtJsonSerializer.
So, I mean QtJsonSerializer encapsulation. I've got a base class

class JsonSerializable 
{
Q_GADGET

public:
  JsonSerializable(const QByteArray& json)
{
//TODO
}

operator QString() const
{
	return toJson();
}

QByteArray toJson() const 
{
	//return result from QtJsonSerializer
}
 

};

But what about creation of this object from QByteArray (JSON) in ctor? I'd like to minimize redundant copies.

Polymorphic Q_GADGETs

Hello! Do you have any hints concerning (de-)serialization of polymorphic Q_GADGETs? They can also have Q_CLASSINFO. I suppose that I have to create a "switch" for property getter/setter which checks some flag in JSON. It will choose, in fact, among variant.value<Class1>(), variant.value<Class2>() and so on for deserialization.

(De-)serializing QObject tree

How can QObject derived object with child objects be used with QtJsonSerializer? I mean that QObject already has children() getter. Is it possible to reuse embedded child-parent methods in collaboration with Q_PROPERTY instead of explicit adding m_children field?

build with Qt5.10.1 on windows and macos got errors

Hi all
I build this source code on windows and macos with Qt5.10.1.but I got some errors

/Qt5.10.1/5.10.1/clang_64/lib/QtCore.framework/Headers/qhashfunctions.h:112:35: error: no matching function for call to 'qHash'
    Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(t)))

 FullValidation = (NoExtraProperties | AllProperties)
//        FullValidation Q_DECL_ENUMERATOR_DEPRECATED_X("Use QJsonSerializer::FullValidation2 or QJsonSerializer::FullPropertyValidation instead") = (NoExtraProperties | AllProperties)

and source code

#if !defined(QT_NO_EXCEPTIONS) //&& QT_CONFIG(future)
#include <QtCore/qexception.h>
#define QT_JSONSERIALIZER_EXCEPTION_BASE QException
#define QT_JSONSERIALIZER_EXCEPTION_OR override
#else
#include <exception>
#define QT_JSONSERIALIZER_EXCEPTION_BASE std::exception
#define QT_JSONSERIALIZER_EXCEPTION_OR
#endif

what's wrong with my platform or build tools?

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.