cJSON的秘密

学习使用cJSON过程的一些发现和总结,不涉及具体的函数

cJSON简介

cJSON是一个快速,高性能的json解析器,由C语言编写,仅包含cJSON.ccJSON.h两个文件,不支持跨平台;跨平台推荐纯lua写的dkjson

cJSON结构体

cJSON结构体的组成:

1
2
3
4
5
6
7
8
9
10
11
12
typedef struct cJSON {
struct cJSON *next, *prev;
struct cJSON *child;

int type;

char *valuestring;
int valueint;
double valuedouble;

char *string;
} cJSON;

其中

  • next指向链表中下一个兄弟节点,prev指向本节点前一个节点
  • child节点只有对象和数组有,并且child节点是双向链表的头节点,childprev一般为NULL,不指向任何节点,双向链表的最后一个兄弟节点的next是无指向的
  • type取值有Null/True/False/Number/String/Array/Object,这些值类型都在cJSON.h中通过宏定义了
  • String类型节点有valuestringNumber类型节点有valueintvaluedouble
  • string表示节点的名称,所有的节点都是一个链表,都具有string

cJSON默认所有值都为0,除非额外为其赋有意义的值

cJSON树结构

cJSON使用树结构存储JSON的各个节点,而这个树结构是使用双向链表实现的(实线表示节点间有真实的引用关系,而虚线表示逻辑上的引用关系):
cJSON树结构

  • 树结构的每一层都是一个双向链表,表示一堆兄弟节点
  • 当前层的所有节点都是当前链表头节点的父节点的子节点

下面举例说明:

1
2
3
4
5
6
7
8
9
10
{
"name": "Jack (\"Bee\") Nimble",
"format": {
"type": "rect",
"width": 1920,
"height": 1080,
"interlace": false,
"frame rate": 24
}
}
  • nameformat节点组成一个链表,typewidthheightinterlaceframe rate节点组成一个链表
  • 根节点包含节点类型Object和子节点name
  • 子节点包含节点名称name、节点值Jack ("Bee") Nimble和兄弟节点format
  • format节点包含节点类型Object、节点名称format和子节点type
  • type节点包含节点类型String、节点名称type、节点值rect和兄弟节点width
  • width节点包含节点类型Number、节点名称width、节点值1920和兄弟节点height
  • height节点包含节点类型Number、节点名称height、节点值1080和兄弟节点interlace
  • interlace节点包含节点类型False、节点名称interlace和兄弟节点frame rate
  • frame rate节点包含节点类型Number、节点名称frame tate和节点值25

cJSON内存管理

cJson分为自动和手动两种使用方式:

  • 在自动模式下,cJSON使用默认的mallocfree函数管理内存,在cJSON中,每个节点都是malloc而来,每个节点的stringvaluestring也是malloc而来,使用cJSON_Delete函数可以递归释放JSON树中malloc的节点内存和字符内存,使用cJSON_Print函数后,则需要手动释放cJSON_Print函数分配的内存,避免内存泄露
  • 在手动模式下,cJSON提供了钩子函数来帮助用户自定义内存管理函数,如果不设置,这默认为mallocfree
1
2
struct cJSON_Hooks js_hook = {xxx_malloc, xxx_free};
cJSON_InitHooks(&js_hook);

cJSON序列化

cJSON序列化就是把cJSON输出,有两种形式:

  • 格式化输出char *cJSON_Print(cJSON *item);
  • 压缩输出char *cJSON_PrintUnformatted(cJSON *item);

需要注意的是cJSON采用了预先将要输的内容全部以字符串形式存储在内存中,最后输出整个字符串的方法,而不是边分析json数据边输出,所以对于比较大的json数据来说,内存就是个问题了

Reference

About me

forthebadge

Creative Commons License This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。