-
Fastest parsing and serialization speed.
-
Wrote by pure C, no ambiguous grammar, easy to understand, compile, use and modify.
-
Only one header file.
-
Tencent is used on a large scale.
- Like copy on write, zzzJSON only parse numbers when using get APIs.
- zzzJSON only judge whether it is a correct number string when parsing JSON string into tree structure.
Simulate nativejson-benchmark
Benchmark | Description |
---|---|
Parse Validation | Use JSON_checker test suite to test whether the library can identify valid and invalid JSONs. (fail01.json is excluded as it is relaxed in [RFC7159]. fail18.json is excluded as depth of JSON is not specified.) |
Parse Double | 66 JSONs, each with a decimal value in an array, are parsed. The parsed double values are compared to the correct answer. |
Parse String | 9 JSONs, each with a string value in an array, are parsed. The parsed strings are compared to the correct answer. |
Roundtrip | 27 condensed JSONs are parsed and stringified. The results are compared to the original JSONs. |
Benchmark | Description |
---|---|
Parse | Parse in-memory JSON into tree structure. |
Stringify | Serialize tree structure into condensed JSON in memory. |
CPU | OS | Compiler | Optimization |
---|---|---|---|
i7-6700 (3.40GHZ) | Ubuntu 18.04(WSL) | G++-7.3 | O3 |
zzzJSON pass all tests.(soure code: conformance_test.cpp)
Name | Parse(ms) | Stringify(ms) | All(ms) |
---|---|---|---|
cjson | 162 | 122 | 284 |
gason | 60 | 321 | 398 |
jsoncpp | 830 | 556 | 1588 |
nlohmannjson | 994 | 312 | 1414 |
picojson | 824 | 295 | 1214 |
rapidjson | 128 | 92 | 224 |
rapidjsonfp | 147 | 91 | 245 |
rapidjsonstr | 127 | 89 | 225 |
taocppjson | 724 | 261 | 1070 |
zzzjson | 86 | 56 | 149 |
Name | Parse(ms) | Stringify(ms) | All(ms) |
---|---|---|---|
arduinojson | 779 | 25 | 807 |
cjson | 53 | 183 | 230 |
gason | 8 | 88 | 93 |
jsoncpp | 88 | 126 | 221 |
nlohmannjson | 62 | 24 | 91 |
parson | 52 | 277 | 336 |
picojson | 54 | 108 | 165 |
rapidjson | 11 | 15 | 23 |
rapidjsonfp | 20 | 17 | 39 |
rapidjsonstr | 24 | 12 | 37 |
taocppjson | 34 | 29 | 66 |
zzzjson | 18 | 7 | 22 |
Name | Parse(ms) | Stringify(ms) | All(ms) |
---|---|---|---|
arduinojson | 23 | 62 | 87 |
cjson | 38 | 23 | 60 |
gason | 9 | 51 | 63 |
jsoncpp | 67 | 51 | 126 |
nlohmannjson | 72 | 29 | 105 |
parson | 48 | 85 | 141 |
picojson | 54 | 35 | 96 |
rapidjson | 18 | 12 | 28 |
rapidjsonfp | 18 | 14 | 30 |
rapidjsonstr | 16 | 12 | 29 |
taocppjson | 47 | 28 | 86 |
zzzjson | 14 | 7 | 23 |
Name | Parse(ms) | Stringify(ms) | All(ms) |
---|---|---|---|
arduinojson | 2056 | 505 | 2508 |
cjson | 243 | 345 | 596 |
gason | 63 | 431 | 500 |
jsoncpp | 451 | 431 | 961 |
nlohmannjson | 518 | 217 | 840 |
parson | 309 | 857 | 1214 |
picojson | 405 | 387 | 862 |
rapidjson | 97 | 119 | 220 |
rapidjsonfp | 113 | 126 | 245 |
rapidjsonstr | 116 | 121 | 240 |
taocppjson | 278 | 207 | 561 |
zzzjson | 95 | 59 | 166 |
Name | Parse(ms) | Stringify(ms) | All(ms) |
---|---|---|---|
cjson | 100 | 107 | 200 |
jsoncpp | 136 | 127 | 284 |
nlohmannjson | 177 | 58 | 242 |
picojson | 94 | 95 | 205 |
rapidjson | 31 | 39 | 56 |
rapidjsonfp | 36 | 19 | 63 |
rapidjsonstr | 37 | 35 | 60 |
taocppjson | 90 | 50 | 143 |
zzzjson | 26 | 16 | 38 |
Name | Parse(ms) | Stringify(ms) | All(ms) |
---|---|---|---|
cjson | 81 | 67 | 155 |
jsoncpp | 130 | 112 | 244 |
nlohmannjson | 199 | 42 | 254 |
picojson | 127 | 93 | 222 |
rapidjson | 24 | 17 | 45 |
rapidjsonfp | 28 | 24 | 46 |
rapidjsonstr | 30 | 24 | 48 |
taocppjson | 100 | 34 | 149 |
zzzjson | 20 | 9 | 29 |
You can use the commands below to get the results above
./build.sh all
#include "zzzjson.h"
#include <stdio.h>
// DeepCopy
void GetAndSet(Value *srcv, Value *desv)
{
// GetType
const JSONType *t;
t = Type(srcv);
if (t == 0)
return;
switch (*t)
{
case JSONTYPEARRAY:
{
// DeepCopy Array
SetArray(desv);
Value *next = Begin(srcv);
while (next != 0)
{
Value *v = NewValue(desv->A);
GetAndSet(next, v);
if (ArrayAddFast(desv, v) != True)
return;
next = Next(next);
}
break;
}
case JSONTYPEOBJECT:
{
// DeepCopy Object
SetObj(desv);
Value *next = Begin(srcv);
while (next != 0)
{
Value *v = NewValue(desv->A);
SetKeyFast(v, GetKey(next));
GetAndSet(next, v);
if (ObjAddFast(desv, v) != True)
return;
next = Next(next);
}
break;
}
case JSONTYPEBOOL:
{
// Copy Bool
const bool *b = GetBool(srcv);
if (b == 0)
return;
SetBool(desv, *b);
break;
}
case JSONTYPENULL:
{
// Copy nil
if (IsNull(srcv) == False)
return;
SetNull(desv);
break;
}
case JSONTYPESTRING:
{
// DeepCopy String
const char *str = GetStr(srcv);
if (str == 0)
return;
if (SetStrFast(desv, str) != True)
return;
break;
}
case JSONTYPENUMBER:
{
// DeepCopy Number
const char *str = GetNumStr(srcv);
if (str == 0)
return;
if (SetNumStrFast(desv, str) != True)
return;
break;
}
}
}
int main()
{
const char *src_json = "[{\"key\":true},false,{\"key1\":true},[null,false,[],true],[\"\",123,\"str\"],null]";
// New Allocator
Allocator *A = NewAllocator();
// New Value
Value *src_v = NewValue(A);
Value *des_v = NewValue(A);
// Parse
BOOL ret = ParseFast(src_v, src_json);
if (ret != True)
{
printf("ParseFast Fail!\n");
return 1;
}
// DeepCopy
GetAndSet(src_v, des_v);
// Stringify
const char *des_json = Stringify(des_v);
printf("src_json:%s\n", src_json);
if (des_json != 0)
printf("des_json:%s\n", des_json);
// Free Allocator
ReleaseAllocator(A);
return 0;
}
Allocator *NewAllocator();
void ReleaseAllocator(Allocator *root_alloc);
Value *NewValue(Allocator *alloc);
BOOL ParseFast(Value *v, const char *s);
BOOL ParseLen(Value *v, const char *s, SIZE len);
BOOL Parse(Value *v, const char *s);
const char *Stringify(const Value *v);
const char *GetStrFast(const Value *v, SIZE *len);
const char *GetUnEscapeStr(Value *v);
const char *GetStr(Value *v);
const char *GetNumFast(const Value *v, zj_SIZE *len);
const char *GetNumStr(Value *v);
const double *GetNum(Value *v);
const double *GetDouble(struct zj_Value *v);
const int *GetInt(struct zj_Value *v);
const long *GetLong(struct zj_Value *v);
const long long *GetLongLong(struct zj_Value *v);
const BOOL *GetBool(const Value *v);
BOOL IsNull(const Value *v);
const char *GetKey(Value *v);
const char *GetUnEscapeKey(Value *v);
const char *GetKeyFast(const Value *v, SIZE *len);
Value *ObjGet(const Value *v, const char *key);
Value *ObjGetLen(const Value *v, const char *key, SIZE len);
const JSONType *Type(const Value *v);
SIZE Size(const Value *v);
Value *ArrayGet(const Value *v, SIZE index);
Value *Begin(const Value *v);
Value *Next(const Value *v);
Value *Copy(const Value *v);
BOOL Move(Value *v);
BOOL SetNull(Value *v);
BOOL SetBool(Value *v, BOOL b);
BOOL SetNumStrFast(Value *v, const char *num);
BOOL SetNumStrLenFast(Value *v, const char *num, SIZE len);
BOOL SetNumStr(Value *v, const char *num);
BOOL SetNumStrLen(Value *v, const char *num, SIZE len);
BOOL SetNum(Value *v, const double d);
BOOL SetDouble(Value *v, const double d);
BOOL SetInt(Value *v, const int d);
BOOL SetLong(Value *v, const long d);
BOOL SetLongLong(Value *v, const long long d);
BOOL SetStrFast(Value *v, const char *str);
BOOL SetStrLenFast(Value *v, const char *str, SIZE len);
BOOL SetStr(Value *v, const char *str);
BOOL SetStrLen(Value *v, const char *str, SIZE len);
BOOL SetStrEscape(Value *v, const char *str);
BOOL SetStrLenEscape(Value *v, const char *str, SIZE len);
BOOL SetKeyFast(Value *v, const char *key);
BOOL SetKeyLenFast(Value *v, const char *key, SIZE len);
BOOL SetKey(Value *v, const char *key);
BOOL SetKeyLen(Value *v, const char *key, SIZE len);
BOOL SetKeyEscape(Value *v, const char *key);
BOOL SetKeyLenEscape(Value *v, const char *key, SIZE len);
BOOL SetArray(Value *v);
BOOL SetObj(Value *v);
BOOL SetFast(Value *v, Value *vv);
BOOL Set(Value *v, const Value *vv);
BOOL ObjAddFast(Value *v, Value *vv);
BOOL ObjAdd(Value *v, const Value *vv);
BOOL ArrayAddFast(Value *v, Value *vv);
BOOL ArrayAdd(Value *v, const Value *vv);
BOOL ArrayDel(Value *v, SIZE index);
BOOL ObjDel(Value *v, const char *key);
define “zj_SHORT_API 0” to use long APIs
#define zj_SHORT_API 0
// must be above to include
#include "zzzjson.h"
struct zj_Allocator *zj_AllocatorNew();
void zj_ReleaseAllocator(struct zj_Allocator *root_alloc);
struct zj_Value *zj_NewValue(struct zj_Allocator *alloc);
bool zj_ParseFast(struct zj_Value *v, const char *s);
bool zj_ParseLen(struct zj_Value *v, const char *s, zj_SIZE len);
bool zj_Parse(struct zj_Value *v, const char *s);
const char *zj_Stringify(const struct zj_Value *v);
const char *zj_GetStrFast(const struct zj_Value *v, zj_SIZE *len);
const char *zj_GetUnEscapeStr(struct zj_Value *v);
const char *zj_GetStr(struct zj_Value *v);
const char *zj_GetNumFast(const struct zj_Value *v, zj_SIZE *len);
const char *zj_GetNumStr(struct zj_Value *v);
const double *zj_GetNum(struct zj_Value *v);
const double *zj_GetDouble(struct zj_Value *v);
const int *zj_GetInt(struct zj_Value *v);
const long *zj_GetLong(struct zj_Value *v);
const long long *zj_GetLongLong(struct zj_Value *v);
const bool *zj_GetBool(const struct zj_Value *v);
bool zj_IsNull(const struct zj_Value *v);
const char *zj_GetKey(struct zj_Value *v);
const char *zj_GetUnEscapeKey(struct zj_Value *v);
const char *zj_GetKeyFast(const struct zj_Value *v, zj_SIZE *len);
struct zj_Value *zj_ObjGet(const struct zj_Value *v, const char *key);
struct zj_Value *zj_ObjGetLen(const struct zj_Value *v, const char *key, zj_SIZE len);
const zj_JSONType *zj_Type(const struct zj_Value *v);
zj_SIZE zj_SizeOf(const struct zj_Value *v);
struct zj_Value *zj_ArrayGet(const struct zj_Value *v, zj_SIZE index);
struct zj_Value *zj_Begin(const struct zj_Value *v);
struct zj_Value *zj_Next(const struct zj_Value *v);
struct zj_Value *zj_Copy(const struct zj_Value *v);
bool zj_Move(struct zj_Value *v);
bool zj_SetNull(struct zj_Value *v);
bool zj_SetBool(struct zj_Value *v, bool b);
bool zj_SetNumStrFast(struct zj_Value *v, const char *num);
bool zj_SetNumStrLenFast(struct zj_Value *v, const char *num, zj_SIZE len);
bool zj_SetNumStr(struct zj_Value *v, const char *num);
bool zj_SetNumStrLen(struct zj_Value *v, const char *num, zj_SIZE len);
bool zj_SetNum(struct zj_Value *v, const double d);
bool zj_SetDouble(struct zj_Value *v, const double d);
bool zj_SetInt(struct zj_Value *v, const int n);
bool zj_SetLong(struct zj_Value *v, const long n);
bool zj_SetLongLong(struct zj_Value *v, const long long n);
bool zj_SetStrFast(struct zj_Value *v, const char *str);
bool zj_SetStrLenFast(struct zj_Value *v, const char *str, zj_SIZE len);
bool zj_SetStr(struct zj_Value *v, const char *str);
bool zj_SetStrLen(struct zj_Value *v, const char *str, zj_SIZE len);
bool zj_SetStrEscape(struct zj_Value *v, const char *str);
bool zj_SetStrLenEscape(struct zj_Value *v, const char *str, zj_SIZE len);
bool zj_SetKeyFast(struct zj_Value *v, const char *key);
bool zj_SetKeyLenFast(struct zj_Value *v, const char *key, zj_SIZE len);
bool zj_SetKey(struct zj_Value *v, const char *key);
bool zj_SetKeyLen(struct zj_Value *v, const char *key, zj_SIZE len);
bool zj_SetKeyEscape(struct zj_Value *v, const char *key);
bool zj_SetKeyLenEscape(struct zj_Value *v, const char *key, zj_SIZE len);
bool zj_SetArray(struct zj_Value *v);
bool zj_SetObj(struct zj_Value *v);
bool zj_SetFast(struct zj_Value *v, struct zj_Value *vv);
bool zj_Set(struct zj_Value *v, const struct zj_Value *vv);
bool zj_ObjAddFast(struct zj_Value *v, struct zj_Value *vv);
bool zj_ObjAdd(struct zj_Value *v, const struct zj_Value *vv);
bool zj_ArrayAddFast(struct zj_Value *v, struct zj_Value *vv);
bool zj_ArrayAdd(struct zj_Value *v, const struct zj_Value *vv);
bool zj_ArrayDel(struct zj_Value *v, zj_SIZE index);
bool zj_ObjDel(struct zj_Value *v, const char *key);