項目地址 https://github.com/kafmws/notfastjson
notfastjson
© 2019 kafm ([email protected])
簡介
簡單 不是很快的 JSON解析庫 C語言實現
- ANSI C標準,跨平臺 / 編譯器
- 遞歸下降解析器
- 支持UTF-8字符
- number類型數字解析僅支持C語言double類型範圍
- 參考 從零開始的 JSON 庫教程 @ Milo Yip
構建
原項目Win平臺下使用VS編寫,使用<crtdbg.h>
及_CRTDBG_MAP_ALLOC
宏檢測內存泄漏
使用宏
#define EXPECT_EQ_BASE(equality, expect, actual, format) \
do {\
test_count++;\
if (equality)\
test_pass++;\
else {\
fprintf(stderr, "%s:%d: expect: " format " actual: " format "\n", __FILE__, __LINE__, expect, actual);\
main_ret = 1;\
}\
} while(0)
構建簡單單元測試
JSON類型
類型 | enum 表示 |
---|---|
null | JSON_NULL |
bool | JSON_TRUE / JSON_FALSE |
number | JSON_NUMBER |
string | JSON_STRING |
array | JSON_ARRAY |
object | JSON_OBJECT |
數據結構
typedef struct nfjson_value nfjson_value;
typedef struct { char *s; size_t len; } nfjson_string;
struct nfjson_value {
union {
nfjson_string s;
struct { nfjson_value *e; size_t len; }a;/* type == JSON_ARRAY */
hash_table *hto;/* type == JSON_OBJECT */
double n;/* type == JSON_NUMBER */
}u;
nfjson_type type;
};
typedef struct {
const char *json;/*the parsing position in the json*/
char *stack;/*parsing buffer*/
size_t size;/*size of stack*/
size_t top;/*pointer of stack*/
}nfjson_context;
類型 | 意義/實現方式 |
---|---|
nfjson_context | JSON字符串解析信息 |
nfjson_value | 解析出的JSON值 |
nfjson_string | UTF-8字符串值 |
hash_table | 通用hash表, 內置使用以nfjson_string爲key類型, nfjson_value爲value類型使用 |
nfjson_context 中 stack | 任意類型動態堆棧, 用作string,array類型解析緩衝區 |
文件目錄
|-- access.c .h //getter & setter
|-- hash_table.c .h //hash_table
|-- memory.c .h //manage memory
|-- nfjson.h //define data structure, error code & json type
|-- parse.c .h //recursive-descent json parser
|-- pch.c .h //VS required
|-- test.c .h //unit testing
其它
- 內存管理
malloc
,realloc
,free
,nfjson_string_free
及遞歸nfjson_free
- 緩衝堆棧
realloc
擴容,任意類型,懸浮指針問題 - 哈希支持 任意類型,按需配置
示例
nfjson_value val;
nfjson_parse(&val,
" { "
"\"n\" : null , "
"\"f\" : false , "
"\"t\" : true , "
"\"i\" : 123 , "
"\"s\" : \"abc\", "
"\"a\" : [ 1, 2, 3 ],"
"\"o\" : { \"1\" : 1, \"2\" : 2, \"3\" : 3 }"
"}"
);
nfjson_get_type(&val) == JSON_OBJECT;
nfjson_get_object_size(&val) == 7;
nfjson_string []s =
{ {"n", 1},{"f", 1},{"t", 1},{"i", 1},{"s", 1},{"a", 1},{"o", 1}, };
//access { "n" : null }
nfjson_value *v = nfjson_get_object_value(&s[0]);
nfjson_get_type(&v) == JSON_NULL;
//access { "i" : 123 }
v = nfjson_get_object_value(&s[3]);
nfjson_get_number(&v) == 123;
//access 1 in { "a" : [1, 2, 3] }
v = nfjson_get_object_value(&s[5]);
nfjson_get_type(&val) == JSON_ARRAY;
nfjson_get_array_size(&val) == 3;
v = nfjson_get_array_element(&v, 1);
nfjson_get_type(&val) == JSON_NUMBER;
nfjson_get_number(&v) == 1;
更多示例見 test.c
notfastjson
© 2019 kafm ([email protected])
Introduction
a simple and not fast json parsing library writed in C
- standard ANSI C,cross-platform / compiler
- recursive decent parser
- UTF-8 char support
- number in range of
double
in C only - based on json-tutorial @ Milo Yip
Build
write in Windows with Visual Studio,using <crtdbg.h>
& macro _CRTDBG_MAP_ALLOC
to detect memory leaks
using following marco
static int test_count = 0;
static int test_pass = 0;
#define EXPECT_EQ_BASE(equality, expect, actual, format) \
do {\
test_count++;\
if (equality)\
test_pass++;\
else {\
fprintf(stderr, "%s:%d: expect: " format " actual: " format "\n", __FILE__, __LINE__, expect, actual);\
main_ret = 1;\
}\
} while(0)
build simple unit testing.
JSON type
type | enum |
---|---|
null | JSON_NULL |
bool | JSON_TRUE / JSON_FALSE |
number | JSON_NUMBER |
string | JSON_STRING |
array | JSON_ARRAY |
object | JSON_OBJECT |
Data Structure
typedef struct nfjson_value nfjson_value;
typedef struct { char *s; size_t len; } nfjson_string;
struct nfjson_value {
union {
nfjson_string s;
struct { nfjson_value *e; size_t len; }a;/* type == JSON_ARRAY */
hash_table *hto;/* type == JSON_OBJECT */
double n;/* type == JSON_NUMBER */
}u;
nfjson_type type;
};
typedef struct {
const char *json;/*the parsing position in the json*/
char *stack;/*parsing buffer*/
size_t size;/*size of stack*/
size_t top;/*pointer of stack*/
}nfjson_context;
type define | meaning/implement |
---|---|
nfjson_context | JSON string context in parsing |
nfjson_value | json value |
nfjson_string | UTF-8 string |
hash_table | a hash table, using nfjson_string as key and nfjson_value as value |
stack in nfjson_context | dynamic stack for any type, as a buffer for json string type and json array type in parsing |
file index
|-- access.c .h //getter & setter
|-- hash_table.c .h //hash_table
|-- memory.c .h //manage memory
|-- nfjson.h //define data structure, error code & json type
|-- parse.c .h //recursive-descent json parser
|-- pch.c .h //VS required
|-- test.c .h //unit testing
Other
- memory managment
malloc
,realloc
,free
,nfjson_string_free
& recursivenfjson_free
- buffer stack
realloc
dynamic expansion,support any type,suspensive pointer problem - hash table support support any type,on-demand configure
examples
nfjson_value val;
nfjson_parse(&val,
" { "
"\"n\" : null , "
"\"f\" : false , "
"\"t\" : true , "
"\"i\" : 123 , "
"\"s\" : \"abc\", "
"\"a\" : [ 1, 2, 3 ],"
"\"o\" : { \"1\" : 1, \"2\" : 2, \"3\" : 3 }"
"}"
);
nfjson_get_type(&val) == JSON_OBJECT;
nfjson_get_object_size(&val) == 7;
nfjson_string []s =
{ {"n", 1},{"f", 1},{"t", 1},{"i", 1},{"s", 1},{"a", 1},{"o", 1}, };
//access { "n" : null }
nfjson_value *v = nfjson_get_object_value(&s[0]);
nfjson_get_type(&v) == JSON_NULL;
//access { "i" : 123 }
v = nfjson_get_object_value(&s[3]);
nfjson_get_number(&v) == 123;
//access 1 in { "a" : [1, 2, 3] }
v = nfjson_get_object_value(&s[5]);
nfjson_get_type(&val) == JSON_ARRAY;
nfjson_get_array_size(&val) == 3;
v = nfjson_get_array_element(&v, 1);
nfjson_get_type(&val) == JSON_NUMBER;
nfjson_get_number(&v) == 1;
for more examples, see test.c