A simple project to test JSON libraries with Delphi and C++Builder.
This is a simple project and not a final product. I know that there are many points that could be better structured. The initial goal was to quickly deploy a single unit "FoMain" kind of project, spending time to include and test the most popular JSON libraries for Delphi. The Delphi version has a simple structure with TLib and TTest classes. Also, it is important to mention that the size of JSON objects used in tests here doesn't represent the most common cases of data manipulation in JSON. Finally, the analysis of the results is not intended to detract from any of the tested libraries and should not be seen as any kind of criticism of the authors of the libraries. Knowledge is freedom.
| Library | Delphi | C++Builder |
|---|---|---|
| McJSON | ✓ | ✓ |
| uLkJSON | ✓ | ✓ |
| System.JSON | ✓ | ✓ |
| JsonDataObjects | ✓ | ✓ |
| SuperObject | ✓ | |
| X-SuperObject | ✓ | |
| JsonTools | ✓ | ✓ |
| Json4Delphi | ✓ | ✓ |
| Grijjy.Bson | ✓ | |
| Neslib.Json | ✓ | |
| dwsJSON | ✓ | |
| chimera.json | ✓ | |
| DynamicDataObjects | ✓ | |
| EasyJson | ✓ | |
| jsonDoc | ✓ |
Note: in order of inclusion.
DelphiVCL 32-bits project built with version12.1(Athens Community Edition).C++BuilderVCL 32-bits project built with version10.2(Tokyo).- Old 64-bits machine: AMD A12-9700P RADEON R7, 10 COMPUTE CORES 4C+6G - 2.50 GHz - 12 GB RAM.
There are three test types:
- Speed Run
- Generate
Nitems{ ... "key_i":"value_i", ... } - Save to file
- Clear
- Load from file
- Find
Mitems - Clone/parse
- Generate
- Validation
- Open File
For each library and test type the app was ran and closed.
The results of Speed Run compute the average time of 5 repetitions.
The Memory consuption is logged and will be part of some results.
This is a performance test with the following configuration (select Default in the Preset list).
N= 50k items.M= 1k items (keep same random sequence for all tests).- 5 repetitions.
Memorycollumn is the app memory consuption after theGenereatesub-test.- It is expected that the
Clone/Parsesub-test consumes twice as memory as theGenerateorLoad from filesub-test. - See images as confirmation.
| Library | Generate | Save | Load | Find | Parse | [Total] | Memory |
|---|---|---|---|---|---|---|---|
Neslib.Json |
.03 s | .03 s | .03 s | .00 s | .04 s | 0.18 s | 10.19 MiB |
Grijjy.Bson |
.03 s | .04 s | .04 s | .00 s | .06 s | 0.23 s | 7.52 MiB |
chimera.json |
.04 s | .03 s | .08 s | .01 s | .08 s | 0.30 s | 8.78 MiB |
McJSON |
.02 s | .06 s | .02 s | .18 s | .08 s | 0.41 s | 9.85 MiB |
System.JSON |
.02 s | .01 s | .06 s | .22 s | .06 s | 0.43 s | 11.38 MiB |
EasyJson |
.02 s | .01 s | .06 s | .23 s | .07 s | 0.45 s | 11.38 MiB |
LkJson |
.06 s | .05 s | .10 s | .01 s | .14 s | 0.45 s | 2.99 MiB |
JsonDoc |
.18 s | .07 s | .11 s | .01 s | .27 s | 0.70 s | 6.14 MiB |
SuperObject |
.13 s | 1.21 s | .05 s | .00 s | .06 s | 1.53 s | 9.68 MiB |
dwsJSON |
.01 s | .01 s | 0.92 s | .03 s | 0.91 s | 1.92 s | 9.88 MiB |
JsonDataObjects |
5.61 s | .01 s | .09 s | .11 s | .10 s | 5.97 s | 8.98 MiB |
JsonTools |
10.36 s | - | - | .22 s | 8.55 s | 19.18 s | 7.88 MiB |
Json4Delphi |
.02 s | .06 s | 35.00 s | .40 s | 35.71 s | 71.23 s | 11.57 MiB |
DynamicDataObjects |
28.73 s | .02 s | 30.24 s | .58 s | 29.25 s | 88.88 s | 11.51 MiB |
X-SuperObject |
5.18 min | .06 s | 1.77 min | 6.18 s | 1.76 min | 8.81 min | 11.48 MiB |
Notes:
- See Conclusions about the
EasyJsonandSystem.JSON. - See Know issues about the incomplete test for
JsonTools.
| Library | Generate | Save | Load | Find | Parse | Total | Memory |
|---|---|---|---|---|---|---|---|
McJSON |
.09 s | .08 s | .04 s | .39 s | .10 s | 0.74 s | 5.09 MiB |
LkJson |
.19 s | .08 s | .16 s | .01 s | .23 s | 0.74 s | 2.88 MiB |
System.JSON |
.12 s | .08 s | .24 s | 2.94 s | .32 s | 3.78 s | 9.39 MiB |
JsonDataObjects |
15.23 s | .02 s | .17 s | .30 s | .19 s | 15.97 s | 4.30 MiB |
JsonTools |
24.41 s | - | - | .46 s | 23.50 s | 48.39 s | 5.78 MiB |
Json4Delphi |
.10 s | .11 s | 63.94 s | .93 s | 64.03 s | 129.17 s | 6.81 MiB |
Notes:
- See Know issues about the incomplete test for
JsonTools.
Here are some results just for the Generate sub-test increasing N using C++Builder project.
| Library | 1k | 5k | 10k | 25k | 50k |
|---|---|---|---|---|---|
McJSON |
.01 s | .02 s | .03 s | .05 s | .10 s |
LkJson |
.01 s | .02 s | .04 s | .10 s | .17 s |
System.JSON |
.01 s | .09 s | .04 s | .07 s | .12 s |
JsonDataObjects |
.01 s | .08 s | .26 s | 2.76 s | 15.55 s |
JsonTools |
.02 s | .12 s | .43 s | 5.51 s | 23.87 s |
Json4Delphi |
.01 s | .02 s | .03 s | .06 s | .11 s |
This validation test should be analyzed carefully. Some libraries have violations for some sort of self-management in reading JSON data.
.\test\validfiles extracted from MJPA/SimpleJSON- These are not valid JSON files because first line has a text as description.
| Library | Expected to Fail but Passed | Expected to Pass but Failed |
|---|---|---|
McJSON |
- | - |
LkJson |
fail(01, 07, 08, 16, 18, 19, 20, 21) | - |
System.JSON |
fail(07) | pass(04) |
JsonDataObjects |
fail(01, 05, 08, 15, 18, 19) | pass(04, 05) |
SuperObject |
fail(01, 06, 07, 08, 10, 11, 16, 18, 19, 20, 21) | - |
X-SuperObject |
fail(01, 06, 08, 15, 16, 17, 18, 19, 20, 21) | pass(01, 04, 05) |
JsonTools |
fail(01, 16, 20, 21) | pass(04, 05) |
Json4Delphi |
- | pass(01, 03, 04, 05, 06) |
Grijjy.Bson |
fail(15, 20) | pass(01, 02, 04, 05) |
Neslib.Json |
fail(07, 15, 16, 18, 19, 20, 21) | pass(04, 05) |
dwsJSON |
fail(16, 18, 19, 21) | - |
chimera.json |
fail(01, 08, 10, 16, 18, 19, 20, 21, 23) | - |
DynamicDataObjects |
fail(05, 06, 07, 09, 16, 17, 18, 19, 20, 21) | pass(01, 05) |
EasyJson |
fail(07) | pass(04, 05) |
JsonDoc |
fail(15, 20, 21) | pass(01, 02, 04, 05) |
| Library | Expected to Fail but Passed | Expected to Pass but Failed |
|---|---|---|
McJSON |
- | - |
LkJson |
fail(01, 07, 08, 16, 18, 19, 20, 21) | - |
System.JSON |
fail(07) | pass(04) |
JsonDataObjects |
fail(01, 05, 08, 15, 18, 19) | pass(04, 05) |
JsonTools |
fail(01, 16, 20, 21) | pass(04, 05) |
Json4Delphi |
- | pass(01, 03, 04, 05, 06) |
List of test files names and description
fail01.json = \x is not a valid escape characterfail02.json = Objects require colon between name/value1111111fail03.json = Objects do not have comma separatorsfail04.json = Arrays don't have colon separatorsfail05.json = Truth is not a valid boolean valuefail06.json = Strings need double quotes, not single quotesfail07.json = Line break in a string value is not validfail08.json = Escaped line break char is still not validfail09.json = Unclosed arrayfail10.json = Numbers require exponent if 'e' is therefail11.json = Only 1 sign char can precede the valuefail12.json = Commas cannot close objectsfail13.json = Brackets must be matchingfail14.json = Double quotes must be escapedfail15.json = Key string must be quotedfail16.json = Arrays must not have comma after last valuefail17.json = Arrays must have values between commasfail18.json = Nothing but whitespace can follow the root valuefail19.json = Each opening bracket must be closedfail20.json = Extra comma after objectfail21.json = Numbers cannot have leading 0sfail22.json = Numbers can't be hex encodedfail23.json = Decimal numbers need a digit before the dotpass01.json = General large array testing valid valuespass02.json = Heavily nested arraypass03.json = Nested objectpass04.json = Simple string valuepass05.json = Unicode character stringpass06.json = From https://json.org/example.html
This is a simple test to open files with any library included into this project. This test will be used in a future update with very large JSON files (+ 100 MiB in size).
-
All
Speed Runtests withDelphiversion are twice as fast as withC++Builder. -
For JSON structures with less than 5000 objects, the choice of libraries can be screened not only based on performance. Standard/Compiler compatibility and ease of use should have priority in terms of choice criterion.
-
Neslib.Jsonis the fastest library tested until now, closely followedGrijjy.Bson. -
LkJsonhas great performance and the lowest memory consumption among all tested libraries. Some changes are needed to use it with Delphi and C++Builder 10.2 in order to save and load UTF-8 encoded files. For some, an obstacle can be that their interfaces are more verbose for C++ usage. For example:
JsonP = dynamic_cast<TlkJSONObject*>(TlkJSON::ParseText(TlkJSON::GenerateText(Json)))-
The
Validationtests can demonstrate that even the most modern libraries can have occasional small violations against the standard. -
For older versions of
DelphiandC++Builder, theMcJSONlibrary can be a good choice in terms of compatibility, ease of use and good performance. -
This project demonstrates some of the facilities and obstacles encountered by C++Builder developers in using libraries developed for Delphi.
-
EasyJsonusesSystem.JSONinternally, so it is expected to see similar results.
TgoBsonDocument.LoadFromJsonFile()failed.SuperObjectcompiles but it is not working with C++Builder. Any help gettingSuperObjectworking with C++Builder is appreciated.JsonToolshad problems saving to file: it was truncated at object"key25412". So,Speed Runtests were ran without theClearandLoad from filesteps.JsonToolsgave an errorRoot node must be an array or objecttrying to load form a UTF-8 file with 50k items file from other sub-tests.chimera.jsonseems to completelly break Delphi 10.4's code completion (Code insight manager = LSP).
These libraries were tested:
- XSuperObject does not compile with
C++Builder10.2. - dwsJSON does not compile with
Delphi10.1 Starter.
There were necessary modifications in order to compile and run some libraries with C++Builder.
uLkJSON:{$DEFINE USE_D2009}TlkJSONstreamed.LoadFromStream();TlkJSONstreamed.SaveToStream();
SuperObject:defined(VER290) or defined(VER300) or defined(VER310) or defined(VER320) or defined(VER330) or defined(VER340) or defined(VER350) or defined(VER360)procedure FromInterface;

