├── .gitignore ├── LICENSE ├── QSerializer ├── README.md ├── _config.yml ├── benchmarks ├── bench.cpp ├── bench.h ├── benchmarks.pro └── testclasses.h ├── example ├── QSerializeExample.pro ├── classes.h ├── general.json ├── general.xml └── main.cpp ├── qserializer.pri └── src └── qserializer.h /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | #ignore thumbnails created by windows 3 | Thumbs.db 4 | #Ignore files build by Visual Studio 5 | *.obj 6 | ;*.exe 7 | *.pdb 8 | *.user 9 | *.aps 10 | *.pch 11 | *.vspscc 12 | *_i.c 13 | *_p.c 14 | *.ncb 15 | *.suo 16 | #*.tlb 17 | *.tlh 18 | *.bak 19 | *.cache 20 | *.ilk 21 | *.log 22 | *.tlog 23 | ;[Bb]in 24 | [Dd]ebug*/ 25 | ;*.lib 26 | *.sbr 27 | obj/ 28 | [Rr]elease*/ 29 | _ReSharper*/ 30 | [Tt]est[Rr]esult* 31 | doc/ 32 | *.rar 33 | *.arj 34 | *.arh 35 | *.scc 36 | *.ipch 37 | *.opensdf 38 | *.sdf 39 | *.opt 40 | *.plg 41 | *.vssscc 42 | *.cd 43 | *.tli 44 | *.crc 45 | Makefile 46 | Makefile.* 47 | #--- *.filters 48 | [Bb]uild-* 49 | .* 50 | *.pro.* 51 | ipch/ 52 | Virtual/ 53 | VSS_BD/ 54 | __WPF__/ 55 | Векторная графика/ 56 | 57 | *.autosave 58 | pictures/log/* 59 | 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020-2021 Agadzhanov Vladimir 4 | Portions Copyright (c) 2021 Jerry Jacobs 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /QSerializer: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "src/qserializer.h" 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [logo]() 2 | 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. 3 | 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. 4 | 5 | ## Installation 6 | Download repository 7 | ```bash 8 | $ git clone https://github.com/smurfomen/QSerializer.git 9 | ``` 10 | Just include qserializer.h in your project and enjoy simple serialization. qserializer.h located in src folder. 11 | Set compiler define `QS_HAS_JSON` or `QS_HAS_XML` for enabling support for xml or json. Enable both at the same time 12 | [is not supported](https://github.com/smurfomen/QSerializer/issues/7). 13 | 14 |
A demo project for using QSerializer located in example folder. 15 | 16 | ## Workflow 17 | To get started, include qserializer.h in your code. 18 | ## Create serialization class 19 | For create serializable member of class and generate propertyes, use macro: 20 | - __QS_FIELD__ 21 | - __QS_COLLECTION__ 22 | - __QS_OBJECT__ 23 | - __QS_COLLECTION_OBJECTS__ 24 | - __QS_QT_DICT__ 25 | - __QS_QT_DICT_OBJECTS__ 26 | - __QS_STL_DICT__ 27 | - __QS_STL_DICT_OBJECTS__ 28 | 29 | If you want only declare exists fields - use macro QS_JSON_FIELD, QS_XML_FIELD, QS_JSON_COLLECTION and other (look at qserializer.h) 30 | ### Inherit from QSerializer 31 | Inherit from QSerializer, use macro QS_SERIALIZABLE or override metaObject method and declare some serializable fields.
32 | In this case you must use Q_GADGET in your class. 33 | ```C++ 34 | class User : public QSerializer 35 | { 36 | Q_GADGET 37 | QS_SERIALIZABLE 38 | // Create data members to be serialized - you can use this members in code 39 | QS_FIELD(int, age) 40 | QS_COLLECTION(QVector, QString, parents) 41 | }; 42 | ``` 43 | ## **Serialize** 44 | Now you can serialize object of this class to JSON or XML. 45 | For example: 46 | ```C++ 47 | User u; 48 | u.age = 20; 49 | u.parents.append("Mary"); 50 | u.parents.append("Jeff"); 51 | 52 | /* case: json value */ 53 | QJsonObject jsonUser = u.toJson(); 54 | 55 | /* case: raw json data */ 56 | QByteArray djson = u.toRawJson(); 57 | 58 | /* case: xml-dom */ 59 | QDomNode xmlUser = u.toXml(); 60 | 61 | /* case: raw xml data */ 62 | QByteArray dxml = u.toRawXml(); 63 | ``` 64 | 65 | ## **Deserialize** 66 | Opposite of the serialization procedure is the deserialization procedure. 67 | You can deserialize object from JSON or XML, declared fields will be modified or resets to default for this type values. 68 | For example: 69 | ```C++ 70 | ... 71 | User u; 72 | 73 | /* case: json value */ 74 | QJsonObject json; 75 | u.fromJson(json); 76 | 77 | /* case: raw json data */ 78 | QByteArray rawJson; 79 | u.fromJson(rawJson); 80 | 81 | /* case: xml-dom */ 82 | QDomNode xml; 83 | u.fromXml(xml); 84 | 85 | /* case: raw xml data */ 86 | QByteArray rawXml; 87 | u.fromXml(rawXml); 88 | ``` 89 | ## Macro description 90 | | Macro | Description | 91 | | --------------------- | ------------------------------------------------------------ | 92 | | QSERIALIZABLE | Make class or struct is serializable to QSerializer (override QMetaObject method and define Q_GADGET macro) | 93 | | QS_FIELD | Create serializable simple field | 94 | | QS_COLLECTION | Create serializable collection values of primitive types | 95 | | QS_OBJECT | Create serializable inner custom type object | 96 | | QS_COLLECTION_OBJECTS | Create serializable collection of custom type objects | 97 | | QS_QT_DICT | Create serializable dictionary of primitive type values FOR QT DICTIONARY TYPES | 98 | | QS_QT_DICT_OBJECTS | Create serializable dictionary of custom type values FOR QT DICTIONARY TYPES | 99 | | QS_STL_DICT | Create serializable dictionary of primitive type values FOR STL DICTIONARY TYPES | 100 | | QS_STL_DICT_OBJECTS | Create serializable dictionary of custom type values FOR STL DICTIONARY TYPES | 101 | | QS_SERIALIZABLE | Override method metaObject and make class serializable | 102 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /benchmarks/bench.cpp: -------------------------------------------------------------------------------- 1 | #include "bench.h" 2 | #include 3 | 4 | void Bench::bench_field_int_toJson() { 5 | TestField_int test; 6 | test.field_int = 999; 7 | QBENCHMARK{ 8 | test.toJson(); 9 | } 10 | } 11 | 12 | void Bench::bench_field_int_toXml() { 13 | TestField_int test; 14 | test.field_int = 999; 15 | QBENCHMARK{ 16 | test.toXml(); 17 | } 18 | } 19 | 20 | void Bench::bench_field_int_fromJson() { 21 | TestField_int test; 22 | test.field_int = 999; 23 | QJsonObject json = test.toJson(); 24 | TestField_int dest; 25 | QBENCHMARK{ 26 | dest.fromJson(json); 27 | } 28 | } 29 | 30 | void Bench::bench_field_int_fromXml() { 31 | TestField_int test; 32 | test.field_int = 999; 33 | QDomNode xml = test.toXml(); 34 | TestField_int dest; 35 | QBENCHMARK{ 36 | dest.fromXml(QSerializer::toByteArray(xml)); 37 | } 38 | } 39 | 40 | void Bench::bench_field_string_toJson() { 41 | TestField_string test; 42 | test.field_string = "QWERTYUIOP{ASDFGHJKL:ZXCVBNM<>?"; 43 | QBENCHMARK{ 44 | test.toJson(); 45 | } 46 | } 47 | 48 | void Bench::bench_field_string_toXml() { 49 | TestField_string test; 50 | test.field_string = "QWERTYUIOP{ASDFGHJKL:ZXCVBNM<>?"; 51 | QBENCHMARK{ 52 | test.toXml(); 53 | } 54 | } 55 | 56 | void Bench::bench_field_string_fromJson() { 57 | TestField_string test; 58 | test.field_string = "QWERTYUIOP{ASDFGHJKL:ZXCVBNM<>?"; 59 | QJsonObject json = test.toJson(); 60 | TestField_string dest; 61 | QBENCHMARK{ 62 | dest.fromJson(json); 63 | } 64 | } 65 | 66 | void Bench::bench_field_string_fromXml() { 67 | TestField_string test; 68 | test.field_string = "QWERTYUIOP{ASDFGHJKL:ZXCVBNM<>?"; 69 | QDomNode xml = test.toXml(); 70 | TestField_string dest; 71 | QBENCHMARK{ 72 | dest.fromXml(QSerializer::toByteArray(xml)); 73 | } 74 | } 75 | 76 | void Bench::bench_collection_vector_int_toJson() { 77 | TestCollection_vector_int test; 78 | for(int i = 0; i < 100; i++) 79 | test.vector_int.append(i); 80 | QBENCHMARK{ 81 | test.toJson(); 82 | } 83 | } 84 | 85 | void Bench::bench_collection_vector_int_toXml() { 86 | TestCollection_vector_int test; 87 | for(int i = 0; i < 100; i++) 88 | test.vector_int.append(i); 89 | QBENCHMARK{ 90 | test.toXml(); 91 | } 92 | } 93 | 94 | void Bench::bench_collection_vector_int_fromJson() { 95 | TestCollection_vector_int test; 96 | for(int i = 0; i < 100; i++) 97 | test.vector_int.append(i); 98 | QJsonObject json = test.toJson(); 99 | TestCollection_vector_int dest; 100 | QBENCHMARK{ 101 | dest.fromJson(json); 102 | } 103 | } 104 | 105 | void Bench::bench_collection_vector_int_fromXml() { 106 | TestCollection_vector_int test; 107 | for(int i = 0; i < 100; i++) 108 | test.vector_int.append(i); 109 | QDomNode xml = test.toXml(); 110 | TestCollection_vector_int dest; 111 | QBENCHMARK{ 112 | dest.fromXml(QSerializer::toByteArray(xml)); 113 | } 114 | } 115 | 116 | void Bench::bench_collection_vector_string_toJson() { 117 | TestCollection_vector_string test; 118 | for(int i = 0; i < 100; i++) 119 | test.vector_string.append(QString::number(i)); 120 | QBENCHMARK{ 121 | test.toJson(); 122 | } 123 | } 124 | 125 | void Bench::bench_collection_vector_string_toXml() { 126 | TestCollection_vector_string test; 127 | for(int i = 0; i < 100; i++) 128 | test.vector_string.append(QString::number(i)); 129 | QBENCHMARK{ 130 | test.toXml(); 131 | } 132 | } 133 | 134 | void Bench::bench_collection_vector_string_fromJson() { 135 | TestCollection_vector_string test; 136 | for(int i = 0; i < 100; i++) 137 | test.vector_string.append(QString::number(i)); 138 | QJsonObject json = test.toJson(); 139 | TestCollection_vector_string dest; 140 | QBENCHMARK{ 141 | dest.fromJson(json); 142 | } 143 | } 144 | 145 | void Bench::bench_collection_vector_string_fromXml() { 146 | TestCollection_vector_string test; 147 | for(int i = 0; i < 100; i++) 148 | test.vector_string.append(QString::number(i)); 149 | QDomNode xml = test.toXml(); 150 | TestCollection_vector_string dest; 151 | QBENCHMARK{ 152 | dest.fromXml(QSerializer::toByteArray(xml)); 153 | } 154 | } 155 | 156 | void Bench::bench_object_field_toJson() { 157 | TestObject_field test; 158 | 159 | test.f_object.f_int = 999; 160 | test.f_object.f_string = "QWERTYUIOP{ASDFGHJKL:ZXCVBNM<>?"; 161 | for(int i = 0; i< 100; i++) 162 | { 163 | test.f_object.v_int.append(i); 164 | test.f_object.v_string.append(QString::number(i)); 165 | } 166 | QBENCHMARK{ 167 | test.toJson(); 168 | } 169 | } 170 | 171 | void Bench::bench_object_field_toXml() { 172 | TestObject_field test; 173 | 174 | test.f_object.f_int = 999; 175 | test.f_object.f_string = "QWERTYUIOP{ASDFGHJKL:ZXCVBNM<>?"; 176 | for(int i = 0; i< 100; i++) 177 | { 178 | test.f_object.v_int.append(i); 179 | test.f_object.v_string.append(QString::number(i)); 180 | } 181 | QBENCHMARK{ 182 | test.toXml(); 183 | } 184 | } 185 | 186 | void Bench::bench_object_field_fromJson() { 187 | TestObject_field test; 188 | 189 | test.f_object.f_int = 999; 190 | test.f_object.f_string = "QWERTYUIOP{ASDFGHJKL:ZXCVBNM<>?"; 191 | for(int i = 0; i< 100; i++) 192 | { 193 | test.f_object.v_int.append(i); 194 | test.f_object.v_string.append(QString::number(i)); 195 | } 196 | QJsonObject json = test.toJson(); 197 | TestObject_field dest; 198 | QBENCHMARK{ 199 | dest.fromJson(json); 200 | } 201 | } 202 | 203 | void Bench::bench_object_field_fromXml() { 204 | TestObject_field test; 205 | 206 | test.f_object.f_int = 999; 207 | test.f_object.f_string = "QWERTYUIOP{ASDFGHJKL:ZXCVBNM<>?"; 208 | for(int i = 0; i< 100; i++) 209 | { 210 | test.f_object.v_int.append(i); 211 | test.f_object.v_string.append(QString::number(i)); 212 | } 213 | 214 | QDomNode xml = test.toXml(); 215 | TestObject_field dest; 216 | QBENCHMARK{ 217 | dest.fromXml(QSerializer::toByteArray(xml)); 218 | } 219 | } 220 | 221 | void Bench::bench_collection_objects_toJson() { 222 | TestObject_collection test; 223 | for(int i = 0; i < 100; i++) 224 | { 225 | Object obj; 226 | obj.f_int = 999; 227 | obj.f_string = "QWERTYUIOP{ASDFGHJKL:ZXCVBNM<>?"; 228 | for(int i = 0; i< 100; i++) 229 | { 230 | obj.v_int.append(i); 231 | obj.v_string.append(QString::number(i)); 232 | } 233 | test.vector_object.append(obj); 234 | } 235 | QBENCHMARK{ 236 | test.toJson(); 237 | } 238 | } 239 | 240 | void Bench::bench_collection_objects_toXml() { 241 | TestObject_collection test; 242 | for(int i = 0; i < 100; i++) 243 | { 244 | Object obj; 245 | obj.f_int = 999; 246 | obj.f_string = "QWERTYUIOP{ASDFGHJKL:ZXCVBNM<>?"; 247 | for(int i = 0; i< 100; i++) 248 | { 249 | obj.v_int.append(i); 250 | obj.v_string.append(QString::number(i)); 251 | } 252 | test.vector_object.append(obj); 253 | } 254 | QBENCHMARK{ 255 | test.toXml(); 256 | } 257 | } 258 | 259 | void Bench::bench_collection_objects_fromJson() { 260 | TestObject_collection test; 261 | for(int i = 0; i < 100; i++) 262 | { 263 | Object obj; 264 | obj.f_int = 999; 265 | obj.f_string = "QWERTYUIOP{ASDFGHJKL:ZXCVBNM<>?"; 266 | for(int i = 0; i< 100; i++) 267 | { 268 | obj.v_int.append(i); 269 | obj.v_string.append(QString::number(i)); 270 | } 271 | test.vector_object.append(obj); 272 | } 273 | QJsonObject json = test.toJson(); 274 | TestObject_collection dest; 275 | QBENCHMARK{ 276 | dest.fromJson(json); 277 | } 278 | } 279 | 280 | void Bench::bench_collection_objects_fromXml() { 281 | TestObject_collection test; 282 | for(int i = 0; i < 100; i++) 283 | { 284 | Object obj; 285 | obj.f_int = 999; 286 | obj.f_string = "QWERTYUIOP{ASDFGHJKL:ZXCVBNM<>?"; 287 | for(int i = 0; i< 5; i++) 288 | { 289 | obj.v_int.append(i); 290 | obj.v_string.append(QString::number(i)); 291 | } 292 | test.vector_object.append(obj); 293 | } 294 | QDomNode xml = test.toXml(); 295 | TestObject_collection dest; 296 | QBENCHMARK{ 297 | dest.fromXml(xml); 298 | } 299 | } 300 | 301 | 302 | 303 | QTEST_MAIN(Bench); 304 | -------------------------------------------------------------------------------- /benchmarks/bench.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCH_H 2 | #define BENCH_H 3 | #include 4 | #include 5 | #include "testclasses.h" 6 | 7 | class Bench : public QObject { 8 | Q_OBJECT 9 | private Q_SLOTS: 10 | //======================================================================================================================================== 11 | void bench_field_int_toJson(); 12 | 13 | void bench_field_int_toXml(); 14 | 15 | void bench_field_int_fromJson(); 16 | 17 | void bench_field_int_fromXml(); 18 | //======================================================================================================================================== 19 | 20 | 21 | 22 | //======================================================================================================================================== 23 | void bench_field_string_toJson(); 24 | 25 | void bench_field_string_toXml(); 26 | 27 | void bench_field_string_fromJson(); 28 | 29 | void bench_field_string_fromXml(); 30 | //======================================================================================================================================== 31 | 32 | 33 | 34 | //======================================================================================================================================== 35 | void bench_collection_vector_int_toJson(); 36 | 37 | void bench_collection_vector_int_toXml(); 38 | 39 | void bench_collection_vector_int_fromJson(); 40 | 41 | void bench_collection_vector_int_fromXml(); 42 | //======================================================================================================================================== 43 | 44 | 45 | 46 | //======================================================================================================================================== 47 | void bench_collection_vector_string_toJson(); 48 | 49 | void bench_collection_vector_string_toXml(); 50 | 51 | void bench_collection_vector_string_fromJson(); 52 | 53 | void bench_collection_vector_string_fromXml(); 54 | //======================================================================================================================================== 55 | 56 | 57 | //======================================================================================================================================== 58 | void bench_object_field_toJson(); 59 | 60 | void bench_object_field_toXml(); 61 | 62 | void bench_object_field_fromJson(); 63 | 64 | void bench_object_field_fromXml(); 65 | //======================================================================================================================================== 66 | 67 | 68 | 69 | //======================================================================================================================================== 70 | void bench_collection_objects_toJson(); 71 | 72 | void bench_collection_objects_toXml(); 73 | 74 | void bench_collection_objects_fromJson(); 75 | void bench_collection_objects_fromXml(); 76 | //======================================================================================================================================== 77 | 78 | }; 79 | 80 | #endif // BENCH_H 81 | -------------------------------------------------------------------------------- /benchmarks/benchmarks.pro: -------------------------------------------------------------------------------- 1 | QT -= gui 2 | QT += testlib 3 | CONFIG += c++11 console 4 | CONFIG -= app_bundle 5 | 6 | # The following define makes your compiler emit warnings if you use 7 | # any Qt feature that has been marked deprecated (the exact warnings 8 | # depend on your compiler). Please consult the documentation of the 9 | # deprecated API in order to know how to port your code away from it. 10 | DEFINES += QT_DEPRECATED_WARNINGS 11 | 12 | # You can also make your code fail to compile if it uses deprecated APIs. 13 | # In order to do so, uncomment the following line. 14 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 15 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 16 | 17 | SOURCES += \ 18 | bench.cpp 19 | 20 | # Default rules for deployment. 21 | qnx: target.path = /tmp/$${TARGET}/bin 22 | else: unix:!android: target.path = /opt/$${TARGET}/bin 23 | !isEmpty(target.path): INSTALLS += target 24 | 25 | include(../src/QSerializer.pri) 26 | 27 | HEADERS += \ 28 | bench.h \ 29 | testclasses.h 30 | -------------------------------------------------------------------------------- /benchmarks/testclasses.h: -------------------------------------------------------------------------------- 1 | #ifndef TESTCLASSES_H 2 | #define TESTCLASSES_H 3 | 4 | #include "../src/qserializer.h" 5 | #include 6 | 7 | class TestField_int { 8 | Q_GADGET 9 | QS_CLASS 10 | QS_FIELD(int, field_int) 11 | }; 12 | 13 | class TestField_string{ 14 | Q_GADGET 15 | QS_CLASS 16 | QS_FIELD(QString, field_string) 17 | }; 18 | 19 | class TestCollection_vector_int { 20 | Q_GADGET 21 | QS_CLASS 22 | QS_COLLECTION(QVector, int, vector_int) 23 | }; 24 | 25 | class TestCollection_vector_string { 26 | Q_GADGET 27 | QS_CLASS 28 | QS_COLLECTION(QVector, QString, vector_string) 29 | }; 30 | 31 | 32 | 33 | class Object 34 | { 35 | Q_GADGET 36 | QS_CLASS 37 | QS_FIELD(int, f_int) 38 | QS_FIELD(QString, f_string) 39 | QS_COLLECTION(QVector, int, v_int) 40 | QS_COLLECTION(QVector, QString, v_string) 41 | }; 42 | 43 | 44 | class TestObject_field { 45 | Q_GADGET 46 | QS_CLASS 47 | QS_OBJECT(Object, f_object) 48 | }; 49 | 50 | 51 | class TestObject_collection{ 52 | Q_GADGET 53 | QS_CLASS 54 | QS_COLLECTION_OBJECTS(QVector, Object, vector_object) 55 | }; 56 | 57 | 58 | #endif // TESTCLASSES_H 59 | -------------------------------------------------------------------------------- /example/QSerializeExample.pro: -------------------------------------------------------------------------------- 1 | QT -= gui 2 | QT += core 3 | CONFIG += c++11 console 4 | CONFIG -= app_bundle 5 | 6 | # The following define makes your compiler emit warnings if you use 7 | # any Qt feature that has been marked deprecated (the exact warnings 8 | # depend on your compiler). Please consult the documentation of the 9 | # deprecated API in order to know how to port your code away from it. 10 | #DEFINES += QT_DEPRECATED_WARNINGS 11 | 12 | # You can also make your code fail to compile if it uses deprecated APIs. 13 | # In order to do so, uncomment the following line. 14 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 15 | # DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060201 # disables all the APIs deprecated before Qt 6.2.1 16 | DEFINES += QS_HAS_JSON 17 | DEFINES += QS_HAS_XML 18 | 19 | include(../qserializer.pri) 20 | 21 | SOURCES += \ 22 | main.cpp 23 | 24 | HEADERS += \ 25 | $$PWD/classes.h 26 | 27 | DISTFILES += \ 28 | $$PWD/general.json \ 29 | $$PWD/general.xml \ 30 | 31 | # Default rules for deployment. 32 | qnx: target.path = /tmp/$${TARGET}/bin 33 | else: unix:!android: target.path = /opt/$${TARGET}/bin 34 | !isEmpty(target.path): INSTALLS += target 35 | -------------------------------------------------------------------------------- /example/classes.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASSES_H 2 | #define CLASSES_H 3 | #include 4 | #include 5 | #include 6 | 7 | class Parent : public QSerializer{ 8 | Q_GADGET 9 | QS_SERIALIZABLE 10 | public: 11 | Parent(){ } 12 | Parent(int age, const QString & name, bool isMale) 13 | : age(age), 14 | name(name), 15 | male(isMale) { } 16 | QS_FIELD(int, age) 17 | QS_FIELD(QString, name) 18 | QS_FIELD(bool, male) 19 | }; 20 | 21 | class Student : public QSerializer { 22 | Q_GADGET 23 | QS_SERIALIZABLE 24 | public: 25 | Student() {} 26 | Student(int age, const QString & name, QStringList links, Parent mom, Parent dad) 27 | : age(age), 28 | name(name), 29 | links(links) 30 | { 31 | parents.append(mom); 32 | parents.append(dad); 33 | } 34 | QS_FIELD(int, age) 35 | QS_FIELD(QString, name) 36 | QS_COLLECTION(QList, QString, links) 37 | QS_COLLECTION_OBJECTS(QList, Parent, parents) 38 | }; 39 | 40 | class Dictionaries : public QSerializer { 41 | Q_GADGET 42 | QS_SERIALIZABLE 43 | QS_QT_DICT(QHash, QString, QString, qt_hash) 44 | QS_QT_DICT(QMap, QString, QString, qt_map) 45 | QS_QT_DICT_OBJECTS(QMap, QString, Student, qt_map_objects); 46 | QS_STL_DICT(std::map, int, QString, std_map) 47 | QS_STL_DICT_OBJECTS(std::map, QString, Student, std_map_objects); 48 | }; 49 | 50 | 51 | class Field : public QSerializer { 52 | Q_GADGET 53 | QS_SERIALIZABLE 54 | QS_FIELD(int, digit) 55 | QS_FIELD(QString, string) 56 | QS_FIELD(bool, flag) 57 | QS_FIELD(double, d_digit) 58 | }; 59 | 60 | 61 | class Collection : public QSerializer{ 62 | Q_GADGET 63 | QS_SERIALIZABLE 64 | QS_COLLECTION(QVector, int, vector) 65 | QS_COLLECTION(QList, QString, list) 66 | QS_COLLECTION(QStack, double, stack) 67 | }; 68 | 69 | 70 | class CustomObject : public QSerializer { 71 | Q_GADGET 72 | QS_SERIALIZABLE 73 | QS_FIELD(int, digit) 74 | QS_COLLECTION(QVector, QString, string) 75 | }; 76 | 77 | 78 | class CollectionOfObjects : public QSerializer{ 79 | Q_GADGET 80 | QS_SERIALIZABLE 81 | QS_COLLECTION_OBJECTS(QVector, CustomObject, objects) 82 | }; 83 | 84 | 85 | class General : public QSerializer{ 86 | Q_GADGET 87 | QS_SERIALIZABLE 88 | QS_OBJECT(Field, field) 89 | QS_OBJECT(Collection, collection) 90 | QS_OBJECT(CustomObject, object) 91 | QS_OBJECT(CollectionOfObjects, collectionObjects) 92 | QS_OBJECT(Dictionaries, dictionaries) 93 | }; 94 | 95 | class TestXmlObject : public QSerializer{ 96 | Q_GADGET 97 | QS_SERIALIZABLE 98 | QS_FIELD(int, digit) 99 | QS_COLLECTION(QVector, QString, string) 100 | }; 101 | 102 | class TestXml : public QSerializer{ 103 | Q_GADGET 104 | QS_SERIALIZABLE 105 | QS_FIELD(int, field) 106 | QS_COLLECTION(QVector, int, collection) 107 | QS_OBJECT(TestXmlObject, object) 108 | }; 109 | 110 | 111 | 112 | #endif // CLASSES_H 113 | -------------------------------------------------------------------------------- /example/general.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection": { 3 | "list": [ 4 | "first", 5 | "second", 6 | "third" 7 | ], 8 | "stack": [ 9 | 2.44, 10 | 4.42, 11 | 77 12 | ], 13 | "vector": [ 14 | 0, 15 | 1, 16 | 2, 17 | 3, 18 | 4, 19 | 5 20 | ] 21 | }, 22 | "collectionObjects": { 23 | "objects": [ 24 | { 25 | "digit": 0, 26 | "string": [ 27 | "so it's just index number in binary 0", 28 | "so it's just index number in binary 1", 29 | "so it's just index number in binary 10", 30 | "so it's just index number in binary 11", 31 | "so it's just index number in binary 100" 32 | ] 33 | }, 34 | { 35 | "digit": 1, 36 | "string": [ 37 | "so it's just index number in binary 1", 38 | "so it's just index number in binary 10", 39 | "so it's just index number in binary 11", 40 | "so it's just index number in binary 100", 41 | "so it's just index number in binary 101" 42 | ] 43 | }, 44 | { 45 | "digit": 2, 46 | "string": [ 47 | "so it's just index number in binary 10", 48 | "so it's just index number in binary 11", 49 | "so it's just index number in binary 100", 50 | "so it's just index number in binary 101", 51 | "so it's just index number in binary 110" 52 | ] 53 | }, 54 | { 55 | "digit": 3, 56 | "string": [ 57 | "so it's just index number in binary 11", 58 | "so it's just index number in binary 100", 59 | "so it's just index number in binary 101", 60 | "so it's just index number in binary 110", 61 | "so it's just index number in binary 111" 62 | ] 63 | }, 64 | { 65 | "digit": 4, 66 | "string": [ 67 | "so it's just index number in binary 100", 68 | "so it's just index number in binary 101", 69 | "so it's just index number in binary 110", 70 | "so it's just index number in binary 111", 71 | "so it's just index number in binary 1000" 72 | ] 73 | } 74 | ] 75 | }, 76 | "dictionaries": { 77 | "qt_hash": { 78 | }, 79 | "qt_map": { 80 | "abra": "kadabra", 81 | "ping": "pong" 82 | }, 83 | "qt_map_objects": { 84 | "+7(909)000-01-00": { 85 | "age": 22, 86 | "links": [ 87 | "http://katelink.com" 88 | ], 89 | "name": "Kate", 90 | "parents": [ 91 | { 92 | "age": 44, 93 | "male": false, 94 | "name": "Marlin" 95 | }, 96 | { 97 | "age": 48, 98 | "male": true, 99 | "name": "Jake" 100 | } 101 | ] 102 | }, 103 | "+7(909)100-00-10": { 104 | "age": 22, 105 | "links": [ 106 | "http://bobsite.com" 107 | ], 108 | "name": "Bob", 109 | "parents": [ 110 | { 111 | "age": 44, 112 | "male": false, 113 | "name": "Mary" 114 | }, 115 | { 116 | "age": 48, 117 | "male": true, 118 | "name": "Koul" 119 | } 120 | ] 121 | } 122 | }, 123 | "std_map": { 124 | "1": "first", 125 | "2": "second" 126 | }, 127 | "std_map_objects": { 128 | "+7(909)000-10-00": { 129 | "age": 21, 130 | "links": [ 131 | "http://somelink.com" 132 | ], 133 | "name": "Jane", 134 | "parents": [ 135 | { 136 | "age": 38, 137 | "male": false, 138 | "name": "Elie" 139 | }, 140 | { 141 | "age": 48, 142 | "male": true, 143 | "name": "John" 144 | } 145 | ] 146 | }, 147 | "+7(909)001-00-00": { 148 | "age": 22, 149 | "links": [ 150 | "http://github.com/smurfomen" 151 | ], 152 | "name": "Ken", 153 | "parents": [ 154 | { 155 | "age": 44, 156 | "male": false, 157 | "name": "Olga" 158 | }, 159 | { 160 | "age": 48, 161 | "male": true, 162 | "name": "Alex" 163 | } 164 | ] 165 | } 166 | } 167 | }, 168 | "field": { 169 | "d_digit": 88.99, 170 | "digit": 34, 171 | "flag": false, 172 | "string": "some string" 173 | }, 174 | "object": { 175 | "digit": 8, 176 | "string": [ 177 | "third", 178 | "second", 179 | "first" 180 | ] 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /example/general.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 34 4 | some string 5 | false 6 | 88.99 7 | 8 | 9 | 10 | 0 11 | 1 12 | 2 13 | 3 14 | 4 15 | 5 16 | 17 | 18 | first 19 | second 20 | third 21 | 22 | 23 | 2.44 24 | 4.42 25 | 77 26 | 27 | 28 | 29 | 8 30 | 31 | third 32 | second 33 | first 34 | 35 | 36 | 37 | 38 | 39 | 0 40 | 41 | so it's just index number in binary 0 42 | so it's just index number in binary 1 43 | so it's just index number in binary 10 44 | so it's just index number in binary 11 45 | so it's just index number in binary 100 46 | 47 | 48 | 49 | 1 50 | 51 | so it's just index number in binary 1 52 | so it's just index number in binary 10 53 | so it's just index number in binary 11 54 | so it's just index number in binary 100 55 | so it's just index number in binary 101 56 | 57 | 58 | 59 | 2 60 | 61 | so it's just index number in binary 10 62 | so it's just index number in binary 11 63 | so it's just index number in binary 100 64 | so it's just index number in binary 101 65 | so it's just index number in binary 110 66 | 67 | 68 | 69 | 3 70 | 71 | so it's just index number in binary 11 72 | so it's just index number in binary 100 73 | so it's just index number in binary 101 74 | so it's just index number in binary 110 75 | so it's just index number in binary 111 76 | 77 | 78 | 79 | 4 80 | 81 | so it's just index number in binary 100 82 | so it's just index number in binary 101 83 | so it's just index number in binary 110 84 | so it's just index number in binary 111 85 | so it's just index number in binary 1000 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 22 100 | Kate 101 | 102 | http://katelink.com 103 | 104 | 105 | 106 | 44 107 | Marlin 108 | false 109 | 110 | 111 | 48 112 | Jake 113 | true 114 | 115 | 116 | 117 | 118 | 119 | 120 | 22 121 | Bob 122 | 123 | http://bobsite.com 124 | 125 | 126 | 127 | 44 128 | Mary 129 | false 130 | 131 | 132 | 48 133 | Koul 134 | true 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 21 148 | Jane 149 | 150 | http://somelink.com 151 | 152 | 153 | 154 | 38 155 | Elie 156 | false 157 | 158 | 159 | 48 160 | John 161 | true 162 | 163 | 164 | 165 | 166 | 167 | 168 | 22 169 | Ken 170 | 171 | http://github.com/smurfomen 172 | 173 | 174 | 175 | 44 176 | Olga 177 | false 178 | 179 | 180 | 48 181 | Alex 182 | true 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /example/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "classes.h" 3 | 4 | #include 5 | #include 6 | 7 | #ifdef QS_HAS_JSON 8 | void json_example() { 9 | qDebug() << "==================================== json_example ===================================="; 10 | Student stud; 11 | stud.age = 23; 12 | stud.name = "Vlad"; 13 | stud.links.append("https:/github.com/smurfomen"); 14 | 15 | Parent mother; 16 | mother.age = 43; 17 | mother.male = false; 18 | mother.name = "Olga"; 19 | 20 | Parent father; 21 | father.age = 48; 22 | father.male = true; 23 | father.name = "Alex"; 24 | stud.parents.append(mother); 25 | stud.parents.append(father); 26 | 27 | qDebug() << "json from object:"; 28 | QByteArray d = stud.toRawJson(); 29 | qDebug() << d.constData(); 30 | 31 | qDebug() << "creation new object using raw json:"; 32 | Student copy; 33 | copy.fromJson(d); 34 | qDebug() << copy.toRawJson().constData(); 35 | qDebug() << "============================================================================="; 36 | } 37 | #endif 38 | 39 | #ifdef QS_HAS_XML 40 | void xml_example(){ 41 | qDebug() << "==================================== xml_example ===================================="; 42 | TestXml src; 43 | src.field = 10; 44 | for(int i = 0; i < src.field; i ++) 45 | src.collection.append(i); 46 | src.object.digit = 666; 47 | src.object.string.append("it's first note in string array"); 48 | src.object.string.append("it's second note in string array"); 49 | 50 | // make hat if need this 51 | QDomDocument node = QSerializer::appendXmlHat(src.toXml(), "UTF-8"); 52 | qDebug() << "xml from object:"; 53 | qDebug() << QSerializer::toByteArray(node).constData(); 54 | 55 | qDebug() << "creation new object using raw xml:"; 56 | TestXml copy; 57 | copy.fromXml(node); 58 | qDebug() << copy.toRawXml().constData(); 59 | qDebug() << "============================================================================="; 60 | } 61 | #endif 62 | 63 | void serialize_to_file() { 64 | /* OBJECT */ 65 | Field field; 66 | field.flag = false; 67 | field.digit = 34; 68 | field.string = "some string"; 69 | field.d_digit = 88.99; 70 | /*.........................................................................................................................*/ 71 | 72 | /* COLLECTION*/ 73 | Collection collection; 74 | collection.list.append("first"); 75 | collection.list.append("second"); 76 | collection.list.append("third"); 77 | for(int i = 0; i < 6; i ++) 78 | collection.vector.append(i); 79 | collection.stack.append(2.44); 80 | collection.stack.append(4.42); 81 | collection.stack.append(77); 82 | /*.........................................................................................................................*/ 83 | 84 | 85 | /* OBJECT */ 86 | CustomObject object; 87 | object.digit = 8; 88 | object.string.append("third"); 89 | object.string.append("second"); 90 | object.string.append("first"); 91 | /*.........................................................................................................................*/ 92 | 93 | 94 | /* COLLECTION OF OBJECTS */ 95 | CollectionOfObjects collectionObjects; 96 | for(int i = 0; i < 5 ; i ++) 97 | { 98 | CustomObject o; 99 | o.digit = i; 100 | for(int k = 0; k < 5; k ++) 101 | o.string.append(QString("so it's just index number in binary %1").arg(QString::number(k+i,2))); 102 | collectionObjects.objects.append(o); 103 | } 104 | /*.........................................................................................................................*/ 105 | 106 | 107 | 108 | /* DICTIONARIES */ 109 | Dictionaries dict; 110 | dict.std_map.insert(std::pair(1,"first")); 111 | dict.std_map.insert(std::pair(2,"second")); 112 | dict.std_map_objects.insert(std::pair("+7(909)001-00-00", Student(22, 113 | "Ken", 114 | QStringList("http://github.com/smurfomen"), 115 | Parent(44, "Olga", false), 116 | Parent(48, "Alex", true)))); 117 | dict.std_map_objects.insert(std::pair("+7(909)000-10-00", Student(21, 118 | "Jane", 119 | QStringList("http://somelink.com"), 120 | Parent(38, "Elie", false), 121 | Parent(48, "John", true)))); 122 | // fill QMap 123 | dict.qt_map_objects.insert("+7(909)000-01-00", Student(22, 124 | "Kate", 125 | QStringList("http://katelink.com"), 126 | Parent(44, "Marlin", false), 127 | Parent(48, "Jake", true))); 128 | dict.qt_map_objects.insert("+7(909)100-00-10", Student(22, 129 | "Bob", 130 | QStringList("http://bobsite.com"), 131 | Parent(44, "Mary", false), 132 | Parent(48, "Koul", true))); 133 | dict.qt_map.insert("ping","pong"); 134 | dict.qt_map.insert("abra","kadabra"); 135 | /*.........................................................................................................................*/ 136 | 137 | General general; 138 | general.field = field; 139 | general.object = object; 140 | general.collection = collection; 141 | general.collectionObjects = collectionObjects; 142 | general.dictionaries = dict; 143 | 144 | #ifdef QS_HAS_JSON 145 | { 146 | qDebug() << "==================================== serialize_to_file : general.json ===================================="; 147 | qDebug() << general.toRawJson().constData(); 148 | 149 | QFile json("general.json"); 150 | if(json.exists()) 151 | json.remove(); 152 | if(json.open(QIODevice::WriteOnly)) 153 | { 154 | json.write(general.toRawJson()); 155 | json.close(); 156 | } 157 | qDebug() << "============================================================================="; 158 | } 159 | #endif 160 | 161 | #ifdef QS_HAS_XML 162 | { 163 | qDebug() << "==================================== serialize_to_file : general.xml ===================================="; 164 | qDebug() << general.toRawXml().constData(); 165 | 166 | QFile xml("general.xml"); 167 | if(xml.exists()) 168 | xml.remove(); 169 | if(xml.open(QIODevice::WriteOnly)) 170 | { 171 | xml.write(general.toRawXml()); 172 | xml.close(); 173 | } 174 | qDebug() << "============================================================================="; 175 | } 176 | #endif 177 | } 178 | 179 | void deserialize_from_file() 180 | { 181 | #ifdef QS_HAS_JSON 182 | { 183 | QFile json ("general.json"); 184 | if(!json.exists()) 185 | qWarning() << "ERROR: general.json is not exist"; 186 | if(json.open(QIODevice::ReadOnly)) 187 | { 188 | // empty object 189 | General general; 190 | qDebug() << "empty json object:"; 191 | qDebug() << general.toRawJson().constData(); 192 | 193 | 194 | general.fromJson(json.readAll()); 195 | qDebug() << "serialized json object from file: general.json"; 196 | qDebug() << general.toRawJson().constData(); 197 | json.close(); 198 | } 199 | } 200 | #endif 201 | 202 | #ifdef QS_HAS_XML 203 | { 204 | QFile xml ("general.xml"); 205 | if(!xml.exists()) 206 | qWarning() << "ERROR: general.xml is not exist"; 207 | if(xml.open(QIODevice::ReadOnly)) 208 | { 209 | // empty object 210 | General general; 211 | qDebug() << "empty xml object:"; 212 | qDebug() << general.toRawXml().constData(); 213 | 214 | qDebug() << "contains in file: general.xml"; 215 | QByteArray d = xml.readAll(); 216 | qDebug() << d << "\n"; 217 | 218 | general.fromXml(d); 219 | qDebug() << "serialized json object from file: general.xml"; 220 | qDebug() << general.toRawXml().constData(); 221 | 222 | xml.close(); 223 | } 224 | } 225 | #endif 226 | } 227 | 228 | int main(int argc, char *argv[]) 229 | { 230 | QCoreApplication a(argc, argv); 231 | qDebug() << "==================================== SERIALIZE EXAMPLES ===================================="; 232 | #ifdef QS_HAS_XML 233 | xml_example(); 234 | #endif 235 | 236 | #ifdef QS_HAS_JSON 237 | json_example(); 238 | #endif 239 | 240 | serialize_to_file(); 241 | deserialize_from_file(); 242 | qDebug() << "============================================================================="; 243 | 244 | return 0; 245 | } 246 | 247 | 248 | 249 | -------------------------------------------------------------------------------- /qserializer.pri: -------------------------------------------------------------------------------- 1 | contains(DEFINES, QS_HAS_XML) { 2 | QT += xml 3 | } 4 | 5 | HEADERS += \ 6 | $$PWD/src/qserializer.h 7 | 8 | INCLUDEPATH += $$PWD/ 9 | 10 | DISTFILES += \ 11 | $$PWD/QSerializer 12 | 13 | CONFIG += QSERIALIZER_INCLUDED 14 | DEFINES += QSERIALIZER_INCLUDED 15 | -------------------------------------------------------------------------------- /src/qserializer.h: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2020-2021 Agadzhanov Vladimir 5 | Portions Copyright (c) 2021 Jerry Jacobs 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | */ 25 | 26 | #ifndef QSERIALIZER_H 27 | #define QSERIALIZER_H 28 | 29 | /* JSON */ 30 | #ifdef QS_HAS_JSON 31 | #include 32 | #include 33 | #include 34 | #include 35 | #endif 36 | 37 | /* XML */ 38 | #ifdef QS_HAS_XML 39 | #include 40 | #include 41 | #endif 42 | 43 | /* META OBJECT SYSTEM */ 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | #include 50 | #include 51 | 52 | #define QS_VERSION "1.2" 53 | 54 | /* Generate metaObject method */ 55 | #define QS_META_OBJECT_METHOD \ 56 | virtual const QMetaObject * metaObject() const { \ 57 | return &this->staticMetaObject; \ 58 | } \ 59 | 60 | #define QSERIALIZABLE \ 61 | Q_GADGET \ 62 | QS_META_OBJECT_METHOD 63 | 64 | /* Mark class as serializable */ 65 | #define QS_SERIALIZABLE QS_META_OBJECT_METHOD 66 | 67 | #ifdef QS_HAS_XML 68 | Q_DECLARE_METATYPE(QDomNode) 69 | Q_DECLARE_METATYPE(QDomElement) 70 | #endif 71 | 72 | class QSerializer { 73 | Q_GADGET 74 | QS_SERIALIZABLE 75 | public: 76 | virtual ~QSerializer() = default; 77 | 78 | #ifdef QS_HAS_JSON 79 | /*! \brief Convert QJsonValue in QJsonDocument as QByteArray. */ 80 | static QByteArray toByteArray(const QJsonValue & value){ 81 | return QJsonDocument(value.toObject()).toJson(); 82 | } 83 | #endif 84 | 85 | #ifdef QS_HAS_XML 86 | /*! \brief Convert QDomNode in QDomDocument as QByteArray. */ 87 | static QByteArray toByteArray(const QDomNode & value) { 88 | QDomDocument doc = value.toDocument(); 89 | return doc.toByteArray(); 90 | } 91 | 92 | /*! \brief Make xml processing instruction (hat) and returns new XML QDomDocument. On deserialization procedure all processing instructions will be ignored. */ 93 | static QDomDocument appendXmlHat(const QDomNode &node, const QString & encoding, const QString & version = "1.0"){ 94 | QDomDocument doc = node.toDocument(); 95 | QDomNode xmlNode = doc.createProcessingInstruction("xml", QString("version=\"%1\" encoding=\"%2\"").arg(version).arg(encoding)); 96 | doc.insertBefore(xmlNode, doc.firstChild()); 97 | return doc; 98 | } 99 | #endif 100 | 101 | 102 | #ifdef QS_HAS_JSON 103 | /*! \brief Serialize all accessed JSON propertyes for this object. */ 104 | QJsonObject toJson() const { 105 | QJsonObject json; 106 | for(int i = 0; i < metaObject()->propertyCount(); i++) 107 | { 108 | #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 109 | if(QString(metaObject()->property(i).typeName()) != QMetaType::typeName(qMetaTypeId())) { 110 | continue; 111 | } 112 | #else 113 | if(metaObject()->property(i).metaType().id() != QMetaType::QJsonValue) { 114 | continue; 115 | } 116 | #endif 117 | 118 | json.insert(metaObject()->property(i).name(), metaObject()->property(i).readOnGadget(this).toJsonValue()); 119 | } 120 | return json; 121 | } 122 | 123 | /*! \brief Returns QByteArray representation this object using json-serialization. */ 124 | QByteArray toRawJson() const { 125 | return toByteArray(toJson()); 126 | } 127 | 128 | /*! \brief Deserialize all accessed XML propertyes for this object. */ 129 | void fromJson(const QJsonValue & val) { 130 | if(val.isObject()) 131 | { 132 | QJsonObject json = val.toObject(); 133 | QStringList keys = json.keys(); 134 | int propCount = metaObject()->propertyCount(); 135 | for(int i = 0; i < propCount; i++) 136 | { 137 | #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 138 | if(QString(metaObject()->property(i).typeName()) != QMetaType::typeName(qMetaTypeId())) { 139 | continue; 140 | } 141 | #else 142 | if(metaObject()->property(i).metaType().id() != QMetaType::QJsonValue) { 143 | continue; 144 | } 145 | #endif 146 | 147 | for(auto key : json.keys()) 148 | { 149 | if(key == metaObject()->property(i).name()) 150 | { 151 | metaObject()->property(i).writeOnGadget(this, json.value(key)); 152 | break; 153 | } 154 | } 155 | } 156 | } 157 | } 158 | 159 | /*! \brief Deserialize all accessed JSON propertyes for this object. */ 160 | void fromJson(const QByteArray & data) { 161 | fromJson(QJsonDocument::fromJson(data).object()); 162 | } 163 | #endif // QS_HAS_JSON 164 | 165 | #ifdef QS_HAS_XML 166 | /*! \brief Serialize all accessed XML propertyes for this object. */ 167 | QDomNode toXml() const { 168 | QDomDocument doc; 169 | QDomElement el = doc.createElement(metaObject()->className()); 170 | for(int i = 0; i < metaObject()->propertyCount(); i++) 171 | { 172 | #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 173 | if(QString(metaObject()->property(i).typeName()) != QMetaType::typeName(qMetaTypeId())) { 174 | continue; 175 | } 176 | #else 177 | if(metaObject()->property(i).metaType().id() != qMetaTypeId()) { 178 | continue; 179 | } 180 | #endif 181 | el.appendChild(QDomNode(metaObject()->property(i).readOnGadget(this).value())); 182 | } 183 | doc.appendChild(el); 184 | return doc; 185 | } 186 | 187 | /*! \brief Returns QByteArray representation this object using xml-serialization. */ 188 | QByteArray toRawXml() const { 189 | return toByteArray(toXml()); 190 | } 191 | 192 | /*! \brief Deserialize all accessed XML propertyes for this object. */ 193 | void fromXml(const QDomNode & val) { 194 | QDomNode doc = val; 195 | 196 | auto n = doc.firstChildElement(metaObject()->className()); 197 | 198 | if(!n.isNull()) { 199 | for(int i = 0; i < metaObject()->propertyCount(); i++) { 200 | QString name = metaObject()->property(i).name(); 201 | QDomElement tmp = metaObject()->property(i).readOnGadget(this).value().firstChildElement(); 202 | 203 | auto f = n.firstChildElement(tmp.tagName()); 204 | metaObject()->property(i).writeOnGadget(this, QVariant::fromValue(f)); 205 | } 206 | } 207 | else 208 | { 209 | for(int i = 0; i < metaObject()->propertyCount(); i++) { 210 | QString name = metaObject()->property(i).name(); 211 | auto f = doc.firstChildElement(name); 212 | metaObject()->property(i).writeOnGadget(this, QVariant::fromValue(f)); 213 | } 214 | } 215 | } 216 | 217 | /*! \brief Deserialize all accessed XML propertyes for this object. */ 218 | void fromXml(const QByteArray & data) { 219 | QDomDocument d; 220 | d.setContent(data); 221 | fromXml(d); 222 | } 223 | #endif // QS_HAS_XML 224 | }; 225 | 226 | #define GET(prefix, name) get_##prefix##_##name 227 | #define SET(prefix, name) set_##prefix##_##name 228 | 229 | /* Create variable */ 230 | #define QS_DECLARE_MEMBER(type, name) \ 231 | public : \ 232 | type name = type(); \ 233 | 234 | /* Create JSON property and methods for primitive type field*/ 235 | #ifdef QS_HAS_JSON 236 | #define QS_JSON_FIELD(type, name) \ 237 | Q_PROPERTY(QJsonValue name READ GET(json, name) WRITE SET(json, name)) \ 238 | private: \ 239 | QJsonValue GET(json, name)() const { \ 240 | QJsonValue val = QJsonValue::fromVariant(QVariant(name)); \ 241 | return val; \ 242 | } \ 243 | void SET(json, name)(const QJsonValue & varname){ \ 244 | name = varname.toVariant().value(); \ 245 | } 246 | #else 247 | #define QS_JSON_FIELD(type, name) 248 | #endif 249 | 250 | /* Create XML property and methods for primitive type field*/ 251 | #ifdef QS_HAS_XML 252 | #define QS_XML_FIELD(type, name) \ 253 | Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name)) \ 254 | private: \ 255 | QDomNode GET(xml, name)() const { \ 256 | QDomDocument doc; \ 257 | QString strname = #name; \ 258 | QDomElement element = doc.createElement(strname); \ 259 | QDomText valueOfProp = doc.createTextNode(QVariant(name).toString()); \ 260 | element.appendChild(valueOfProp); \ 261 | doc.appendChild(element); \ 262 | return QDomNode(doc); \ 263 | } \ 264 | void SET(xml, name)(const QDomNode &node) { \ 265 | if(!node.isNull() && node.isElement()){ \ 266 | QDomElement domElement = node.toElement(); \ 267 | if(domElement.tagName() == #name) \ 268 | name = QVariant(domElement.text()).value(); \ 269 | } \ 270 | } 271 | #else 272 | #define QS_XML_FIELD(type, name) 273 | #endif 274 | 275 | /* Generate JSON-property and methods for primitive type objects */ 276 | /* This collection must be provide method append(T) (it's can be QList, QVector) */ 277 | #ifdef QS_HAS_JSON 278 | #define QS_JSON_ARRAY(itemType, name) \ 279 | Q_PROPERTY(QJsonValue name READ GET(json, name) WRITE SET(json, name)) \ 280 | private: \ 281 | QJsonValue GET(json, name)() const { \ 282 | QJsonArray val; \ 283 | for(int i = 0; i < name.size(); i++) \ 284 | val.push_back(name.at(i)); \ 285 | return QJsonValue::fromVariant(val); \ 286 | } \ 287 | void SET(json, name)(const QJsonValue & varname) { \ 288 | if(!varname.isArray()) \ 289 | return; \ 290 | name.clear(); \ 291 | QJsonArray val = varname.toArray(); \ 292 | for(auto item : val) { \ 293 | itemType tmp; \ 294 | tmp = item.toVariant().value(); \ 295 | name.append(tmp); \ 296 | } \ 297 | } 298 | #else 299 | #define QS_JSON_ARRAY(itemType, name) 300 | #endif 301 | 302 | /* Generate XML-property and methods for primitive type objects */ 303 | /* This collection must be provide method append(T) (it's can be QList, QVector) */ 304 | #ifdef QS_HAS_XML 305 | #define QS_XML_ARRAY(itemType, name) \ 306 | Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name)) \ 307 | private: \ 308 | QDomNode GET(xml, name)() const { \ 309 | QDomDocument doc; \ 310 | QString strname = #name; \ 311 | QDomElement arrayXml = doc.createElement(QString(strname)); \ 312 | arrayXml.setAttribute("type", "array"); \ 313 | \ 314 | for(int i = 0; i < name.size(); i++) { \ 315 | itemType item = name.at(i); \ 316 | QDomElement itemXml = doc.createElement("item"); \ 317 | itemXml.setAttribute("type", #itemType); \ 318 | itemXml.setAttribute("index", i); \ 319 | itemXml.appendChild(doc.createTextNode(QVariant(item).toString())); \ 320 | arrayXml.appendChild(itemXml); \ 321 | } \ 322 | \ 323 | doc.appendChild(arrayXml); \ 324 | return QDomNode(doc); \ 325 | } \ 326 | void SET(xml, name)(const QDomNode & node) { \ 327 | QDomNode domNode = node.firstChild(); \ 328 | name.clear(); \ 329 | while(!domNode.isNull()) { \ 330 | if(domNode.isElement()) { \ 331 | QDomElement domElement = domNode.toElement(); \ 332 | name.append(QVariant(domElement.text()).value()); \ 333 | } \ 334 | domNode = domNode.nextSibling(); \ 335 | } \ 336 | } 337 | #else 338 | #define QS_XML_ARRAY(itemType, name) 339 | #endif 340 | 341 | 342 | /* Generate JSON-property and methods for some custom class */ 343 | /* Custom type must be provide methods fromJson and toJson or inherit from QSerializer */ 344 | #ifdef QS_HAS_JSON 345 | #define QS_JSON_OBJECT(type, name) \ 346 | Q_PROPERTY(QJsonValue name READ GET(json, name) WRITE SET(json, name)) \ 347 | private: \ 348 | QJsonValue GET(json, name)() const { \ 349 | QJsonObject val = name.toJson(); \ 350 | return QJsonValue(val); \ 351 | } \ 352 | void SET(json, name)(const QJsonValue & varname) { \ 353 | if(!varname.isObject()) \ 354 | return; \ 355 | name.fromJson(varname); \ 356 | } 357 | #else 358 | #define QS_JSON_OBJECT(type, name) 359 | #endif 360 | 361 | /* Generate XML-property and methods for some custom class */ 362 | /* Custom type must be provide methods fromJson and toJson or inherit from QSerializer */ 363 | #ifdef QS_HAS_XML 364 | #define QS_XML_OBJECT(type, name) \ 365 | Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name)) \ 366 | private: \ 367 | QDomNode GET(xml, name)() const { \ 368 | return name.toXml(); \ 369 | } \ 370 | void SET(xml, name)(const QDomNode & node){ \ 371 | name.fromXml(node); \ 372 | } 373 | #else 374 | #define QS_XML_OBJECT(type, name) 375 | #endif 376 | 377 | /* Generate JSON-property and methods for collection of custom type objects */ 378 | /* Custom item type must be provide methods fromJson and toJson or inherit from QSerializer */ 379 | /* This collection must be provide method append(T) (it's can be QList, QVector) */ 380 | #ifdef QS_HAS_JSON 381 | #define QS_JSON_ARRAY_OBJECTS(itemType, name) \ 382 | Q_PROPERTY(QJsonValue name READ GET(json, name) WRITE SET(json, name)) \ 383 | private: \ 384 | QJsonValue GET(json, name)() const { \ 385 | QJsonArray val; \ 386 | for(int i = 0; i < name.size(); i++) \ 387 | val.push_back(name.at(i).toJson()); \ 388 | return QJsonValue::fromVariant(val); \ 389 | } \ 390 | void SET(json, name)(const QJsonValue & varname) { \ 391 | if(!varname.isArray()) \ 392 | return; \ 393 | name.clear(); \ 394 | QJsonArray val = varname.toArray(); \ 395 | for(int i = 0; i < val.size(); i++) { \ 396 | itemType tmp; \ 397 | tmp.fromJson(val.at(i)); \ 398 | name.append(tmp); \ 399 | } \ 400 | } 401 | #else 402 | #define QS_JSON_ARRAY_OBJECTS(itemType, name) 403 | #endif 404 | 405 | /* Generate XML-property and methods for collection of custom type objects */ 406 | /* Custom type must be provide methods fromXml and toXml or inherit from QSerializer */ 407 | /* This collection must be provide method append(T) (it's can be QList, QVector) */ 408 | #ifdef QS_HAS_XML 409 | #define QS_XML_ARRAY_OBJECTS(itemType, name) \ 410 | Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name)) \ 411 | private: \ 412 | QDomNode GET(xml, name)() const { \ 413 | QDomDocument doc; \ 414 | QDomElement element = doc.createElement(#name); \ 415 | element.setAttribute("type", "array"); \ 416 | for(int i = 0; i < name.size(); i++) \ 417 | element.appendChild(name.at(i).toXml()); \ 418 | doc.appendChild(element); \ 419 | return QDomNode(doc); \ 420 | } \ 421 | void SET(xml, name)(const QDomNode & node) { \ 422 | name.clear(); \ 423 | QDomNodeList nodesList = node.childNodes(); \ 424 | for(int i = 0; i < nodesList.size(); i++) { \ 425 | itemType tmp; \ 426 | tmp.fromXml(nodesList.at(i)); \ 427 | name.append(tmp); \ 428 | } \ 429 | } 430 | #else 431 | #define QS_XML_ARRAY_OBJECTS(itemType, name) 432 | #endif 433 | 434 | /* Generate JSON-property and methods for dictionary of simple fields (int, bool, QString, ...) */ 435 | /* Custom type must be inherit from QSerializer */ 436 | /* This collection must be provide method insert(KeyT, ValueT) (it's can be QMap, QHash) */ 437 | /* THIS IS FOR QT DICTIONARY TYPES, for example QMap, QMap, ...*/ 438 | #ifdef QS_HAS_JSON 439 | #define QS_JSON_QT_DICT(map, name) \ 440 | Q_PROPERTY(QJsonValue name READ GET(json, name) WRITE SET(json,name)) \ 441 | private: \ 442 | QJsonValue GET(json, name)() const { \ 443 | QJsonObject val; \ 444 | for(auto p = name.constBegin(); p != name.constEnd(); ++p) { \ 445 | val.insert( \ 446 | QVariant(p.key()).toString(), \ 447 | QJsonValue::fromVariant(QVariant(p.value()))); \ 448 | } \ 449 | return val; \ 450 | } \ 451 | void SET(json, name)(const QJsonValue & varname) { \ 452 | QJsonObject val = varname.toObject(); \ 453 | name.clear(); \ 454 | for(auto p = val.constBegin() ;p != val.constEnd(); ++p) { \ 455 | name.insert( \ 456 | QVariant(p.key()).value(), \ 457 | QVariant(p.value()).value()); \ 458 | } \ 459 | } 460 | #else 461 | #define QS_JSON_QT_DICT(map, name) 462 | #endif 463 | 464 | /* Generate XML-property and methods for dictionary of simple fields (int, bool, QString, ...) */ 465 | /* Custom type must be inherit from QSerializer */ 466 | /* This collection must be provide method insert(KeyT, ValueT) (it's can be QMap, QHash) */ 467 | /* THIS IS FOR QT DICTIONARY TYPES, for example QMap, QMap, ...*/ 468 | #ifdef QS_HAS_XML 469 | #define QS_XML_QT_DICT(map, name) \ 470 | Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name)) \ 471 | private: \ 472 | QDomNode GET(xml, name)() const { \ 473 | QDomDocument doc; \ 474 | QDomElement element = doc.createElement(#name); \ 475 | element.setAttribute("type", "map"); \ 476 | for(auto p = name.begin(); p != name.end(); ++p) \ 477 | { \ 478 | QDomElement e = doc.createElement("item"); \ 479 | e.setAttribute("key", QVariant(p.key()).toString()); \ 480 | e.setAttribute("value", QVariant(p.value()).toString()); \ 481 | element.appendChild(e); \ 482 | } \ 483 | doc.appendChild(element); \ 484 | return QDomNode(doc); \ 485 | } \ 486 | void SET(xml, name)(const QDomNode & node) { \ 487 | if(!node.isNull() && node.isElement()) \ 488 | { \ 489 | QDomElement root = node.toElement(); \ 490 | if(root.tagName() == #name) \ 491 | { \ 492 | QDomNodeList childs = root.childNodes(); \ 493 | \ 494 | for(int i = 0; i < childs.size(); ++i) { \ 495 | QDomElement item = childs.at(i).toElement(); \ 496 | name.insert(QVariant(item.attributeNode("key").value()).value(), \ 497 | QVariant(item.attributeNode("value").value()).value()); \ 498 | } \ 499 | } \ 500 | } \ 501 | } 502 | #else 503 | #define QS_XML_QT_DICT(map, name) 504 | #endif 505 | 506 | 507 | /* Generate JSON-property and methods for dictionary of custom type objects */ 508 | /* Custom type must be inherit from QSerializer */ 509 | /* This collection must be provide method inserv(KeyT, ValueT) (it's can be QMap, QHash) */ 510 | /* THIS IS FOR QT DICTIONARY TYPES, for example QMap */ 511 | #ifdef QS_HAS_JSON 512 | #define QS_JSON_QT_DICT_OBJECTS(map, name) \ 513 | Q_PROPERTY(QJsonValue name READ GET(json, name) WRITE SET(json,name)) \ 514 | private: \ 515 | QJsonValue GET(json, name)() const { \ 516 | QJsonObject val; \ 517 | for(auto p = name.begin(); p != name.end(); ++p) { \ 518 | val.insert( \ 519 | QVariant::fromValue(p.key()).toString(), \ 520 | p.value().toJson()); \ 521 | } \ 522 | return val; \ 523 | } \ 524 | void SET(json, name)(const QJsonValue & varname) { \ 525 | QJsonObject val = varname.toObject(); \ 526 | name.clear(); \ 527 | for(auto p = val.constBegin();p != val.constEnd(); ++p) { \ 528 | map::mapped_type tmp; \ 529 | tmp.fromJson(p.value()); \ 530 | name.insert( \ 531 | QVariant(p.key()).value(), \ 532 | tmp); \ 533 | } \ 534 | } 535 | #else 536 | #define QS_JSON_QT_DICT_OBJECTS(map, name) 537 | #endif 538 | 539 | /* Generate XML-property and methods for dictionary of custom type objects */ 540 | /* Custom type must be inherit from QSerializer */ 541 | /* This collection must be provide method insert(KeyT, ValueT) (it's can be QMap, QHash) */ 542 | /* THIS IS FOR QT DICTIONARY TYPES, for example QMap */ 543 | #ifdef QS_HAS_XML 544 | #define QS_XML_QT_DICT_OBJECTS(map, name) \ 545 | Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name)) \ 546 | private: \ 547 | QDomNode GET(xml, name)() const { \ 548 | QDomDocument doc; \ 549 | QDomElement element = doc.createElement(#name); \ 550 | element.setAttribute("type", "map"); \ 551 | for(auto p = name.begin(); p != name.end(); ++p) \ 552 | { \ 553 | QDomElement e = doc.createElement("item"); \ 554 | e.setAttribute("key", QVariant(p.key()).toString()); \ 555 | e.appendChild(p.value().toXml()); \ 556 | element.appendChild(e); \ 557 | } \ 558 | doc.appendChild(element); \ 559 | return QDomNode(doc); \ 560 | } \ 561 | void SET(xml, name)(const QDomNode & node) { \ 562 | if(!node.isNull() && node.isElement()) \ 563 | { \ 564 | QDomElement root = node.toElement(); \ 565 | if(root.tagName() == #name) \ 566 | { \ 567 | QDomNodeList childs = root.childNodes(); \ 568 | \ 569 | for(int i = 0; i < childs.size(); ++i) { \ 570 | QDomElement item = childs.at(i).toElement(); \ 571 | map::mapped_type tmp; \ 572 | tmp.fromXml(item.firstChild()); \ 573 | name.insert(QVariant(item.attributeNode("key").value()).value(), \ 574 | tmp); \ 575 | } \ 576 | } \ 577 | } \ 578 | } 579 | #else 580 | #define QS_XML_QT_DICT_OBJECTS(map, name) 581 | #endif 582 | 583 | /* Generate JSON-property and methods for dictionary of simple fields (int, bool, QString, ...) */ 584 | /* Custom type must be inherit from QSerializer */ 585 | /* This collection must be provide method insert(KeyT, ValueT) (it's can be std::map) */ 586 | /* THIS IS FOR STL DICTIONARY TYPES, for example std::map, std::map, ...*/ 587 | #ifdef QS_HAS_JSON 588 | #define QS_JSON_STL_DICT(map, name) \ 589 | Q_PROPERTY(QJsonValue name READ GET(json, name) WRITE SET(json,name)) \ 590 | private: \ 591 | QJsonValue GET(json, name)() const { \ 592 | QJsonObject val; \ 593 | for(auto p : name){ \ 594 | val.insert( \ 595 | QVariant::fromValue(p.first).toString(), \ 596 | QJsonValue::fromVariant(QVariant(p.second))); \ 597 | } \ 598 | return val; \ 599 | } \ 600 | void SET(json, name)(const QJsonValue & varname) { \ 601 | QJsonObject val = varname.toObject(); \ 602 | name.clear(); \ 603 | for(auto p = val.constBegin();p != val.constEnd(); ++p) { \ 604 | name.insert(std::pair( \ 605 | QVariant(p.key()).value(), \ 606 | QVariant(p.value()).value())); \ 607 | } \ 608 | } 609 | #else 610 | #define QS_JSON_STL_DICT(map, name) 611 | #endif 612 | 613 | #ifdef QS_HAS_XML 614 | #define QS_XML_STL_DICT(map, name) \ 615 | Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name)) \ 616 | private: \ 617 | QDomNode GET(xml, name)() const { \ 618 | QDomDocument doc; \ 619 | QDomElement element = doc.createElement(#name); \ 620 | element.setAttribute("type", "map"); \ 621 | for(auto p : name) \ 622 | { \ 623 | QDomElement e = doc.createElement("item"); \ 624 | e.setAttribute("key", QVariant(p.first).toString()); \ 625 | e.setAttribute("value", QVariant(p.second).toString()); \ 626 | element.appendChild(e); \ 627 | } \ 628 | doc.appendChild(element); \ 629 | return QDomNode(doc); \ 630 | } \ 631 | void SET(xml, name)(const QDomNode & node) { \ 632 | if(!node.isNull() && node.isElement()) \ 633 | { \ 634 | QDomElement root = node.toElement(); \ 635 | if(root.tagName() == #name) \ 636 | { \ 637 | QDomNodeList childs = root.childNodes(); \ 638 | \ 639 | for(int i = 0; i < childs.size(); ++i) { \ 640 | QDomElement item = childs.at(i).toElement(); \ 641 | name.insert(std::pair( \ 642 | QVariant(item.attributeNode("key").value()).value(), \ 643 | QVariant(item.attributeNode("value").value()).value())); \ 644 | } \ 645 | } \ 646 | } \ 647 | } 648 | #else 649 | #define QS_XML_STL_DICT(map, name) 650 | #endif 651 | 652 | /* Generate JSON-property and methods for dictionary of custom type objects */ 653 | /* Custom type must be inherit from QSerializer */ 654 | /* This collection must be provide method insert(KeyT, ValueT) (it's can be std::map) */ 655 | /* THIS IS FOR STL DICTIONARY TYPES, for example std::map */ 656 | #ifdef QS_HAS_JSON 657 | #define QS_JSON_STL_DICT_OBJECTS(map, name) \ 658 | Q_PROPERTY(QJsonValue name READ GET(json, name) WRITE SET(json,name)) \ 659 | private: \ 660 | QJsonValue GET(json, name)() const { \ 661 | QJsonObject val; \ 662 | for(auto p : name){ \ 663 | val.insert( \ 664 | QVariant::fromValue(p.first).toString(), \ 665 | p.second.toJson()); \ 666 | } \ 667 | return val; \ 668 | } \ 669 | void SET(json, name)(const QJsonValue & varname) { \ 670 | QJsonObject val = varname.toObject(); \ 671 | name.clear(); \ 672 | for(auto p = val.constBegin(); p != val.constEnd(); ++p) { \ 673 | map::mapped_type tmp; \ 674 | tmp.fromJson(p.value()); \ 675 | name.insert(std::pair( \ 676 | QVariant(p.key()).value(), \ 677 | tmp)); \ 678 | } \ 679 | } 680 | #else 681 | #define QS_JSON_STL_DICT_OBJECTS(map, name) 682 | #endif 683 | 684 | /* Generate XML-property and methods for dictionary of custom type objects */ 685 | /* Custom type must be inherit from QSerializer */ 686 | /* This collection must be provide method insert(KeyT, ValueT) (it's can be std::map) */ 687 | /* THIS IS FOR STL DICTIONARY TYPES, for example std::map */ 688 | #ifdef QS_HAS_XML 689 | #define QS_XML_STL_DICT_OBJECTS(map, name) \ 690 | Q_PROPERTY(QDomNode name READ GET(xml, name) WRITE SET(xml, name)) \ 691 | private: \ 692 | QDomNode GET(xml, name)() const { \ 693 | QDomDocument doc; \ 694 | QDomElement element = doc.createElement(#name); \ 695 | element.setAttribute("type", "map"); \ 696 | for(auto p : name) \ 697 | { \ 698 | QDomElement e = doc.createElement("item"); \ 699 | e.setAttribute("key", QVariant(p.first).toString()); \ 700 | e.appendChild(p.second.toXml()); \ 701 | element.appendChild(e); \ 702 | } \ 703 | doc.appendChild(element); \ 704 | return QDomNode(doc); \ 705 | } \ 706 | void SET(xml, name)(const QDomNode & node) { \ 707 | if(!node.isNull() && node.isElement()) \ 708 | { \ 709 | QDomElement root = node.toElement(); \ 710 | if(root.tagName() == #name) \ 711 | { \ 712 | QDomNodeList childs = root.childNodes(); \ 713 | \ 714 | for(int i = 0; i < childs.size(); ++i) { \ 715 | QDomElement item = childs.at(i).toElement(); \ 716 | map::mapped_type tmp; \ 717 | tmp.fromXml(item.firstChild()); \ 718 | name.insert(std::pair ( \ 719 | QVariant(item.attributeNode("key").value()).value(), \ 720 | tmp)); \ 721 | } \ 722 | } \ 723 | } \ 724 | } 725 | #else 726 | #define QS_XML_STL_DICT_OBJECTS(map, name) 727 | #endif 728 | 729 | 730 | /* BIND: */ 731 | /* generate serializable propertyes JSON and XML for primitive type field */ 732 | #define QS_BIND_FIELD(type, name) \ 733 | QS_JSON_FIELD(type, name) \ 734 | QS_XML_FIELD(type, name) \ 735 | 736 | /* BIND: */ 737 | /* generate serializable propertyes JSON and XML for collection of primitive type fields */ 738 | #define QS_BIND_COLLECTION(itemType, name) \ 739 | QS_JSON_ARRAY(itemType, name) \ 740 | QS_XML_ARRAY(itemType, name) \ 741 | 742 | /* BIND: */ 743 | /* generate serializable propertyes JSON and XML for custom type object */ 744 | #define QS_BIND_OBJECT(type, name) \ 745 | QS_JSON_OBJECT(type, name) \ 746 | QS_XML_OBJECT(type, name) \ 747 | 748 | /* BIND: */ 749 | /* generate serializable propertyes JSON and XML for collection of custom type objects */ 750 | #define QS_BIND_COLLECTION_OBJECTS(itemType, name) \ 751 | QS_JSON_ARRAY_OBJECTS(itemType, name) \ 752 | QS_XML_ARRAY_OBJECTS(itemType, name) \ 753 | 754 | /* BIND: */ 755 | /* generate serializable propertyes JSON and XML for dictionary with primitive value type for QT DICTIONARY TYPES */ 756 | #define QS_BIND_QT_DICT(map, name) \ 757 | QS_JSON_QT_DICT(map, name) \ 758 | QS_XML_QT_DICT(map, name) \ 759 | 760 | /* BIND: */ 761 | /* generate serializable propertyes JSON and XML for dictionary of custom type objects for QT DICTIONARY TYPES */ 762 | #define QS_BIND_QT_DICT_OBJECTS(map, name) \ 763 | QS_JSON_QT_DICT_OBJECTS(map, name) \ 764 | QS_XML_QT_DICT_OBJECTS(map,name) \ 765 | 766 | 767 | /* BIND: */ 768 | /* generate serializable propertyes JSON and XML for dictionary with primitive value type for STL DICTIONARY TYPES */ 769 | #define QS_BIND_STL_DICT(map, name) \ 770 | QS_JSON_STL_DICT(map, name) \ 771 | QS_XML_STL_DICT(map, name) \ 772 | 773 | 774 | /* BIND: */ 775 | /* generate serializable propertyes JSON and XML for dictionary of custom type objects for STL DICTIONARY TYPES */ 776 | #define QS_BIND_STL_DICT_OBJECTS(map, name) \ 777 | QS_JSON_STL_DICT_OBJECTS(map, name) \ 778 | QS_XML_STL_DICT_OBJECTS(map,name) \ 779 | 780 | 781 | 782 | /* CREATE AND BIND: */ 783 | /* Make primitive field and generate serializable propertyes */ 784 | /* For example: QS_FIELD(int, digit), QS_FIELD(bool, flag) */ 785 | #define QS_FIELD(type, name) \ 786 | QS_DECLARE_MEMBER(type, name) \ 787 | QS_BIND_FIELD(type, name) \ 788 | 789 | /* CREATE AND BIND: */ 790 | /* Make collection of primitive type objects [collectionType name] and generate serializable propertyes for this collection */ 791 | /* This collection must be provide method append(T) (it's can be QList, QVector) */ 792 | #define QS_COLLECTION(collectionType, itemType, name) \ 793 | QS_DECLARE_MEMBER(collectionType, name) \ 794 | QS_BIND_COLLECTION(itemType, name) \ 795 | 796 | /* CREATE AND BIND: */ 797 | /* Make custom class object and bind serializable propertyes */ 798 | /* This class must be inherited from QSerializer */ 799 | #define QS_OBJECT(type,name) \ 800 | QS_DECLARE_MEMBER(type, name) \ 801 | QS_BIND_OBJECT(type, name) \ 802 | 803 | /* CREATE AND BIND: */ 804 | /* Make collection of custom class objects [collectionType name] and bind serializable propertyes */ 805 | /* This collection must be provide method append(T) (it's can be QList, QVector) */ 806 | #define QS_COLLECTION_OBJECTS(collectionType, itemType, name) \ 807 | QS_DECLARE_MEMBER(collectionType, name) \ 808 | QS_BIND_COLLECTION_OBJECTS(itemType, name) \ 809 | 810 | 811 | /* CREATE AND BIND: */ 812 | /* Make dictionary collection of simple types [dictionary name] and bind serializable propertyes */ 813 | /* This collection must be QT DICTIONARY TYPE */ 814 | #define QS_QT_DICT(map, first, second, name) \ 815 | public: \ 816 | typedef map dict_##name##_t; \ 817 | dict_##name##_t name = dict_##name##_t(); \ 818 | QS_BIND_QT_DICT(dict_##name##_t, name) \ 819 | 820 | /* CREATE AND BIND: */ 821 | /* Make dictionary collection of custom class objects [dictionary name] and bind serializable propertyes */ 822 | /* This collection must be QT DICTIONARY TYPE */ 823 | #define QS_QT_DICT_OBJECTS(map, first, second, name) \ 824 | public: \ 825 | typedef map dict_##name##_t; \ 826 | dict_##name##_t name = dict_##name##_t(); \ 827 | QS_BIND_QT_DICT_OBJECTS(dict_##name##_t, name) \ 828 | 829 | /* CREATE AND BIND: */ 830 | /* Make dictionary collection of simple types [dictionary name] and bind serializable propertyes */ 831 | /* This collection must be STL DICTIONARY TYPE */ 832 | #define QS_STL_DICT(map, first, second, name) \ 833 | public: \ 834 | typedef map dict_##name##_t; \ 835 | dict_##name##_t name = dict_##name##_t(); \ 836 | QS_BIND_STL_DICT(dict_##name##_t, name) \ 837 | 838 | /* CREATE AND BIND: */ 839 | /* Make dictionary collection of custom class objects [dictionary name] and bind serializable propertyes */ 840 | /* This collection must be STL DICTIONARY TYPE */ 841 | #define QS_STL_DICT_OBJECTS(map, first, second, name) \ 842 | public: \ 843 | typedef map dict_##name##_t; \ 844 | dict_##name##_t name = dict_##name##_t(); \ 845 | QS_BIND_STL_DICT_OBJECTS(dict_##name##_t, name) \ 846 | 847 | 848 | 849 | #endif // QSERIALIZER_H 850 | 851 | --------------------------------------------------------------------------------