@Christian Schmitz, I ran those speed tests. They are in a separate branch on the repo. As you can see, except for creation, your plugin is faster than either the native or my class.
The “but they don’t match” messages are because the native will encode some Unicode characters. I don’t know the reason why it picks those. The output from the MBS plugin matches the output from my class with EncodeUnicode set to false.
All times are in microseconds.
JSONItem Create: 13,032
JSONItem_MTC Create: 6,422
JSONMBS Create: 14,082
JSONItem.ToString: 240,627
JSONItem_MTC.ToString: 23,235
JSONMBS.ToString: 2,818
JSONItem.Load: 145,182
JSONItem_MTC.Load: 45,637
JSONMBS.Load: 1,862
JSONItem.Create (big): 24,989
JSONItem_MTC.Create (big): 32,765
JSONMBS.Create (big): 241,766
JSONItem.ToString (big): 4,557,413
JSONItem_MTC.ToString (big): 78,576
... but they don't match
JSONMBS.ToString (big): 4,094
... but it doesn't match JSONItem
JSONItem.Load (big): 322,309
JSONItem_MTC.Load (big): 183,231
JSONMBS.Load (big): 5,061
(For my European friends, remember that “13,032” means thirteen-thousand, thirty-two microseconds, not 13 and 32/1000 microseconds. In the “big” test, the native class ToString takes around four-and-a-half seconds.)
I’ve updated the project. My class will now accept any escaped character in a JSON string (which it may according to the RFC), added pragmas for some additional speed, and added code to better handle encoding when loading a JSON string. It will figure out the correct encoding (ignoring whatever encoding that’s already set) and even strip any BOM that might be present.
I’m about to update again. This time I’ve made it so that all output is through a MemoryBlock and Ptr instead of an array. The latest numbers are improved, although MBS still blows it away for most operations.
In a compiled app:
JSONItem Create: 12,301
JSONItem_MTC Create: 6,481
JSONMBS Create: 14,421
JSONItem.ToString: 250,623
JSONItem_MTC.ToString: 17,857
JSONMBS.ToString: 3,131
JSONItem.Load: 144,455
JSONItem_MTC.Load: 46,604
JSONMBS.Load: 2,220
JSONItem.Create (big): 27,334
JSONItem_MTC.Create (big): 33,889
JSONMBS.Create (big): 241,615
JSONItem.ToString (big): 4,624,553
JSONItem_MTC.ToString (big): 45,137
... but they don't match
JSONMBS.ToString (big): 4,182
... but it doesn't match JSONItem
JSONItem.Load (big): 328,129
JSONItem_MTC.Load (big): 186,690
JSONMBS.Load (big): 4,642
All times are in microseconds, and there are no decimals.
Again, the “but it doesn’t match” message is because JSONItem encodes some Unicode characters while neither JSONItem_MTC nor JSONMBS does. The output is valid on all cases.
If I knew why JSONItem encoded those particular characters, I’d emulate that, but I can’t find a good reason in the RFC or other sources. It would help to hear the reasoning from some engineer.
In the meantime, you can choose to encode all Unicode characters (code point > 127) by setting EncodeUnicode to true before calling ToString.
// ascii control characters and unicode chars that javascript can’t handle
// since we use this with web edition code it HAS to work in java script too
chr 0-31
chr 127
&h00ad
&h0600 - &h0604
&h070f
&h17b4 - &h17b5
&h200c - &h200f
&h2028 - &h202f
&h2060 - &h206f
&hfeff
&hfff0 - &hffff
BTW, I added a unit test to confirm that all characters from &h0000 through &hFFFF are represented the same as the native class. Now I just have to figure out the right way to handle encoding and reading of characters > &hFFFF when EncodeUnicode is true.
I just updated the project to v.2.3. In the latest, doubles with the values INF or NAN will be output that way regardless of the format string. This is a break with both the native class and the JSON RFC which does not allow those values, so
I introduced a Strict property. By default, it is set to False, but when set to True, the class conforms strictly to the RFC. This means values like “TRUE”, “+1”, and “inf” will be rejected, and doubles that are either INF or NAN will raise an exception rather than being output. With Strict turned on, you can use JSONItem_MTC as a JSON validator, and the string output should be valid with all other JSON implementations.
Now updated to 2.4. The class will now properly decode and (if EncodeType.All) encode characters whose code point > &hFFFF.
@Greg O’Lone, I wanted to call your attention to this one as the native class does not handle this properly. I included a unit test within the project to demonstrate, and will find or start a FR soon.
As a test, use the JSON string:
["\\uD834\\uDD1E"]
That should decode to &u1D11E, but instead gives an invalid string.