JsonWax for Qt

NOW WITH SERIALIZATION

------ JsonWax JsonWax JsonWax --- JsonWax JsonWax JsonWax ------------ JsonWax JsonWax JsonWax ---- JsonWax JsonWax JsonWax ------------- JsonWax JsonWax JsonWax ---------- JsonWax JsonWax JsonWax ----------- JsonWax JsonWax JsonWax -------- JsonWax JsonWax JsonWax ------------ JsonWax JsonWax JsonWax ------- JsonWax JsonWax JsonWax JsonWax JsonWax JsonWax --------- JsonWax JsonWax JsonWax ----------- JsonWax JsonWax JsonWax -- JsonWax JsonWax JsonWax -------------- JsonWax JsonWax JsonWax ---------- JsonWax JsonWax JsonWax -------- JsonWax JsonWax JsonWax ---- JsonWax JsonWax JsonWax --------- JsonWax JsonWax JsonWax ---- JsonWax JsonWax JsonWax -- JsonWax JsonWax JsonWax ---------- JsonWax JsonWax JsonWax --------- JsonWax JsonWax JsonWax ------------- JsonWax JsonWax JsonWax - JsonWax JsonWax JsonWax ---------- JsonWax JsonWax JsonWax ----------- JsonWax JsonWax JsonWax ------------ JsonWax JsonWax JsonWax ---------- JsonWax JsonWax JsonWax -------------- JsonWax JsonWax JsonWax ------- JsonWax JsonWax JsonWax JsonWax JsonWax JsonWax -------- JsonWax JsonWax JsonWax ----- JsonWax JsonWax JsonWax JsonWax JsonWax JsonWax

JSON COMPLIANCE

JsonWax can handle any JSON-document adhering to the JSON standard. This includes handling numbers and escaped characters.

PERFORMANCE

Unfortunately, JsonWax isn't as fast at internalizing a document as QJsonDocument is. To test the speed, create a folder named "speedtest" in your working-directory, and fill it up with .json documents. Include JsonWaxTests.h, then run the line:

JsonWaxInternals::Tests::speedTest();

This will load all the files, and compare the time it takes to parse the files (comparing only the differences between parsing from memory). I ran this test with about 40 MB worth of JSON-documents, and JsonWax internalizes documents with time spent being about 4 times of Qt's class. Below you can see a comparison of the relative speeds under specific circumstances. These values vary depending on the compiler and the system. Lowest value means fastest.

QJsonDocument Task JsonWax
1 Parse and internalize a document. 3.3 to 4.7
1 Read 20,000 values from array, depth 0 16 to 24
1 Read 20,000 values from array, depth 5 21 to 22
1 to 18 Change 20,000 values in array, depth 0 1 to 7.5
1 to 1.2 Change 20,000 values in array, depth 5 1 to 7.7

WILL IT WORK ON A QT VERSION EARLIER THAN 5.7?

Probably not. 5.6 might work. In Qt 5.5, certain classes don't like being static, which means: crash when destructing. I really would like to fix this problem, since it means JsonWax won't work on Windows XP. Other than that, there are problems when converting number values to string. The Qt 5.5 version of QVariant preferred a different conversion style, i.e. writing all possible digits of a Double value, instead of only the relevant ones (so, a lot more 0's than expected).

THREAD-SAFETY

JsonWax is NOT thread-safe. You can interact with multiple JsonWax objects simultaneously, in separate threads, but you should only interact with the object from that same thread (or it'll crash).

ESCAPED CHARACTERS

JsonWax reads UTF-8 text files and converts any unicode code points and escaped characters to their respective characters. This means that value(keys).toString() always returns de-escaped characters. When writing special characters (\,",\b,\f,\n,\r,\t) to a file, the characters are converted to escaped form. UTF-8 characters aren't converted to escaped form, unless you choose so, by using the convertToCodePoints-argument in the save()-functions.

SERIALIZING OBJECTS

The serializeToBytes() function uses QDataStream, and its serialization depends on your version of Qt. So, if you want the serialized data to always be readable, independent of what version of Qt you are currently running, you should set the versions on the QDataStreams. In order to do so, you must uncomment the three stream.setVersion(...); lines in JsonWaxSerializer.h, and choose a version number (I'll make it simpler in the future).

In Qt there are at least 2 ways of serializing objects: Via QTextStream, which serializes the object to a string, and via QDataStream, which serializes to a byte array. In QObject, per default, there is support for serializing its member variables to QVariants. Look in the Qt docs for: "Serializing Qt Data Types" to see how many types QDataStream can (de)serialize.

In JsonWax you can use any of the three methods of (de)serializing:
serializeToJson(), which uses QTextStream.
serializeToBytes(), which uses QDataStream.
• Having it as a member variable of a QObject, then serializeToJson() or serializeToBytes().

I've overloaded the operators for the Q..Streams, so anything that can be serialized in a normal Qt can be serialized by JsonWax.
If you use serializeToBytes(), the object is converted to a Base64 byteArray, which is then stored as a string in the JSON-document. This string is unreadable, and you'd get better performance and use less space if you serialized objects to regular byte arrays, and then stored them in a binary file, instead of a JSON-document. However, it's many times faster at serializing and deserializing than serializeToJson().

If you use serializeToJson(), the defining member values of the object are stored as readable strings in the JSON-document. See under "serializeToJson", which Qt data types are supported.

IN CASE OF PARSING ERRORS

If the JSON-document is invalid, JsonWax will store all values until the point where the document became invalid. You can edit that document as normal.

JsonWax json;
json.fromByteArray("[{\"A\":\"zebra\"},{\"B\":f\"koala\"},{\"C\":\"wolf\"}]");
json.saveAs( "out.json");

There is an 'f' between "B:" and "koala", which is invalid JSON. "out.json" contains only:

[
  {
    "A": "zebra"
  }
]

Let's try a different scenario.

JsonWax json;
json.fromByteArray("[{\"A\":\"cow\"},{\"B\":1565f},{\"C\":\"lion\"}]");
json.saveAs( "out.json");

The number ends with an invalid character 'f'. JsonWax will stop parsing, so "out.json" contains:

[
  {
    "A": "cow"
  },
  {
    "B": 1565
  }
]