学习使用cJSON过程的一些发现和总结,不涉及具体的函数
cJSON简介
cJSON
是一个快速,高性能的json
解析器,由C
语言编写,仅包含cJSON.c
和cJSON.h
两个文件,不支持跨平台;跨平台推荐纯lua
写的dkjson
cJSON结构体
cJSON
结构体的组成:
1 | typedef struct cJSON { |
其中
next
指向链表中下一个兄弟节点,prev
指向本节点前一个节点child
节点只有对象和数组有,并且child
节点是双向链表的头节点,child
的prev
一般为NULL
,不指向任何节点,双向链表的最后一个兄弟节点的next
是无指向的type
取值有Null/True/False/Number/String/Array/Object
,这些值类型都在cJSON.h
中通过宏定义了String
类型节点有valuestring
,Number
类型节点有valueint
和valuedouble
string
表示节点的名称,所有的节点都是一个链表,都具有string
值
cJSON
默认所有值都为0
,除非额外为其赋有意义的值
cJSON树结构
cJSON
使用树结构存储JSON
的各个节点,而这个树结构是使用双向链表实现的(实线表示节点间有真实的引用关系,而虚线表示逻辑上的引用关系):
- 树结构的每一层都是一个双向链表,表示一堆兄弟节点
- 当前层的所有节点都是当前链表头节点的父节点的子节点
下面举例说明:
1 | { |
name
和format
节点组成一个链表,type
、width
、height
、interlace
和frame 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
使用默认的malloc
和free
函数管理内存,在cJSON
中,每个节点都是malloc
而来,每个节点的string
和valuestring
也是malloc
而来,使用cJSON_Delete
函数可以递归释放JSON
树中malloc
的节点内存和字符内存,使用cJSON_Print
函数后,则需要手动释放cJSON_Print
函数分配的内存,避免内存泄露 - 在手动模式下,
cJSON
提供了钩子函数来帮助用户自定义内存管理函数,如果不设置,这默认为malloc
和free
1 | struct cJSON_Hooks js_hook = {xxx_malloc, xxx_free}; |
cJSON序列化
cJSON
序列化就是把cJSON
输出,有两种形式:
- 格式化输出
char *cJSON_Print(cJSON *item);
- 压缩输出
char *cJSON_PrintUnformatted(cJSON *item);
需要注意的是cJSON
采用了预先将要输的内容全部以字符串形式存储在内存中,最后输出整个字符串的方法,而不是边分析json
数据边输出,所以对于比较大的json
数据来说,内存就是个问题了