前言
楼主是CS的毕业生,虽然不是编程新手,但是在校期间都没有做过大规模的项目,于是想从网上学习一些开源项目来弥补自己的经验,这是第一次解释开源的源代码,出于柿子还是挑软捏这个原则,盯上了只有一千行代码的cJSON。从test.c文件开始,逐步调试程序的执行过程,通过画出数据结构来解读源代码,过程如下
JSON是什么
通过阅读下面的页面来了解JSON的信息:http://www.json.org/json-zh.html
我从这里下载了cJSON的源代码http://sourceforge.net/projects/cjson/
可以了解到JSON具有两种形式,一种是由键值对(key/value)集合组成的对象(object),另一种是由值(value)的集合组成的数组。其中,key的类型是字符串类型,因为JSON允许结构嵌套,所以value的类型则有很多种,包括:字符串,数字,对象,数组,true,false,null
cJSON的解释原理:
1. cJSON分为三步来处理:解释,渲染和输出
2. 解释阶段:对输入的字符串进行特征识别,例如提取字符串中的单词,数字等,并把这些提取出来的特征分别组合成一个节点,然后用树(树的某些节点是双向链表)把这些节点连接起来。
3. 渲染阶段:提取树中每个节点里的信息,放在一个字符串缓冲区中,最后输出缓冲区里的内容
4.输出阶段:把缓冲区里的内容输出即可
用代码描述JSON的一个节点结构如下:
typedef struct cJSON { struct cJSON *next,*prev; /*该节点指向前后节点的指针*/ struct cJSON *child; /*一个数组节点或者对象节点会拥有一个指向由子节点组成的链表的指针 int type; /*节点的类型 */ char *valuestring; /* 如果这个节点的type等于cJSON_String,就会具有这个字段的信息 */ int valueint; /* 如果这个节点的type等于cJSON_Number,就会具有这个字段的信息*/ double valuedouble; /* 如果这个节点的type等于cJSON_Number,就会具有这个字段的信息*/ char *string; /* 如果这个节点是一个儿子节点或者某个object的子节点的集合,这个字段表明了这个节点的名字 */ } cJSON;
那么每个节点的type究竟有哪些呢?
/* cJSON Types: */ #define cJSON_False 0 #define cJSON_True 1 #define cJSON_NULL 2 #define cJSON_Number 3 #define cJSON_String 4 #define cJSON_Array 5 #define cJSON_Object 6 #define cJSON_IsReference 256 #define cJSON_StringIsConst 512
cJSON节点管理
创建节点
/* 分配一个JSON节点的内存,并且用0填充该节点的内容*/ static cJSON *cJSON_New_Item(void) { cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); if (node) memset(node,0,sizeof(cJSON)); return node; }
注意这里使用到的函数cJSON_malloc(),cJSON使用了hook技术,使得用户可以自己定制内存的分配和释放函数,在默认的情况下,cJSON使用的是C语言中的malloc和free函数。代码如下:
static void *(*cJSON_malloc)(size_t sz) = malloc; //cJSON_malloc是一个函数指针的指针 static void (*cJSON_free)(void *ptr) = free; //cJSON_free是一个函数指针 /*用户可以选择是否使用自定义的内存管理函数*/ void cJSON_InitHooks(cJSON_Hooks* hooks) { if (!hooks) { /*