cJSON源码分析
-
简介
由于C语言汇总,没有直接的字典,字符串数组等数据结构,所以要借助结构体定义,处理json。
JSON是一种轻量级的数据交换格式。JSON采用完全独立与语言的文本格式,易于人阅读和编写。同时也易于机器解析和生成。它是基于javascript,Programming Language,Standard ECMA-262 3rd Edition -December 1999的一个子集。JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(如C,C++,C++,JavaScript,Perl,Python等)。这些特性使用JSON成为理想的数据交换语言。
JSON作用:在数据传输时能够更好地提取出需要的数据,可以用于客户端和服务器端的数据交互。
JSON建构与两种结构:
- “名称/值”对的集合。不同的语言中,它被理解为对象(Object),记录(Record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(Key list),或者关联数组(Associative array)。
- 值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组(array)。
JSON的结构可以理解成无序的、可嵌套的key-value键值对集合,这些key-value键值对是以结构体或数组的形式来组织的。同一级的key-value键值对之间是用以个“,”(逗号)隔开,每个key-value键值对是由一个key后面紧接一个“:”(冒号),冒号后面是这个key对应的value。Key是一个word,由大小写字母、下划线及数字组成,可以由双引号封闭,也可以不加双引号;而value值的取值为:字符串(string),数值(number),true,false,null,对象(object)或者数组(array)。这些结构可以嵌套。
实质:JSON是一种信息交换格式,而cJSON就是对JSON格式的字符串进行构建和解析的一个C语言函数库。此外,cJSON作为JSON格式的解析库,其主要功能就是构建和解析JSON格式。
JSON具有的形式如下:
对象是一个无序的“名称/值”对集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’”对之间使用“,”(逗号)分割。其具体形式如下图:
数值是值(value)的有序集合。一个数组以“[”(左中括号)开始,“]”(右中括号)结束。值之间使用“,”(逗号)分割。其具体形式如下图:
值(value)可以是双引号括起来的字符串(string)、数值(number)、true、false、null、对象(object)或者数组(array)。这些结构可以嵌套。其具体形式如下:
字符串(string)是由双引号包围的任意数量Unicode字符的集合,使用反斜线转义。一个字符(character)即一个单独的字符馋(character string)。字符串(string)与C或者Java的字符串非常相似。其具体形式如下:
数值(number)也与C或者Java的数值非常相似。除去未曾使用的八进制与十六进制格式。除去一些编码细节。其具体形式如下:
JSON格式举例如下:
1 对象: 名称/值的集合 2 例:{"firstName":"Tom"} 3 数组: 值的序列 4 例:[310, null, 0.231, -2.3E+5] 5 字符串: 6 例:"cJSON" 7 数字: 8 例:500 9 布尔值: 10 例:true false
-
cJSON源码分析
1)cJSON源码下载,网址为: http://sourceforge.net/projects/cjson/。
2)解压后,主要参看的源码文件为cJSON.h和sJSON.c和test.c,其中test.c为测试函数。
由于cJSON为JSON格式的解析库,故主要功能是构建和解析JSON格式。其中的结构体,函数定义实现等都是围绕这两个函数实现。下面将对其源码进行分析。
JSON的内存结构不是树,像广义表,可以认为是有层次的双向链表。
cJSON中的重要接口函数如下:
1 解析函数 2 cJSON * cJSON_Parse(const char *value); 3 打印函数 4 char * cJSON_Print(cJSON * item); 5 删除函数 6 void cJSON_Delete(cJSON * c); 7 构造函数 8 create系列和add系列 9 解析字符串 10 char *parse_string(cJSON*item,const char *str) 11 解析数字 12 char *parse_number(cJSON *item,const char *num) 13 解析数组 14 char *parse_array(cJSON *item,const char *value) 15 解析对象 16 char *parse_object(cJSON *item,const char *value) 17 ......
-
cJSON程序中的细节点如下:
- 大量宏替换
- 大量静态函数
- 错误处理机制
- 字符串处理时存在utf16转utf9,编码转换
- 用函数指针封装malloc,free,方便用于处理,比如在申请后初始化,或者释放前进行一些处理等。
CJSON的节点结构体如下:
1 // JSON的一个value的结构体 2 typedef struct cJSON 3 { 4 struct cJSON *next,*prev; // 同一级的元素使用双向列表存储 5 struct cJSON *child; // 如果是一个object或array的话,child为第一个儿子的指针 6 7 int type; // value的类型 8 9 char *valuestring; // 如果这个value是字符串类型,则此处为字符串值 10 int valueint; // 如果是数字的话,整数值 11 double valuedouble; // 如果是数字的话,读点数值 12 13 char *string; // 如果是对象的key-value元素的话,key值 14 } cJSON; 15 16 // JSON的类型 17 #define cJSON_False 0 18 #define cJSON_True 1 19 #define cJSON_NULL 2 20 #define cJSON_Number 3 21 #define cJSON_String 4 22 #define cJSON_Array 5 23 #define cJSON_Object 6 24 25 #define cJSON_IsReference 256 26 #define cJSON_StringIsConst 512
cJSON中的内存管理使用了HOOK技术,主要是为了方便使用者自己定义内存管理函数,即用户自定义的malloc和free。下面对其内存管理相关程序分析。
1 // json内存管理 2 // 为方便用户自由的管理内存,其使用了Hook技术让使用者可以自定义内存管理函数 3 typedef struct cJSON_Hooks 4 { 5 void *(*malloc_fn)(size_t sz); 6 void (*free_fn)(void *ptr); 7 } cJSON_Hooks; 8 9 // 对cJSON提供的分配,再分配,释放内存初始化函数 10 extern void cJSON_InitHooks(cJSON_Hooks* hooks); 11 12 // 默认将分配和释放空间函数指针指向malloc和free 13 static void *(*cJSON_malloc)(size_t sz) = malloc; 14 static void (*cJSON_free)(void *ptr) = free; 15 // 其使用Hook技术来让使用者可以自定义内存管理函数。其中默认系统使用的内存分配和释放函数是malloc 16 // 和free函数,利用cJSON_InitHooks函数可以替换成用户自定义的malloc和free函数。 17 void cJSON_InitHooks(cJSON_Hooks* hooks) 18 { 19 // 如果未定义,则使用默认的malloc和free函数 20 if (!hooks) { /* Reset hooks */ 21 cJSON_malloc = malloc; 22 cJSON_free = free; 23 return; 24 } 25 // 定义了,则使用用户自定义的malloc和free函数 26 cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; 27 cJSON_free = (hooks->free_fn)?hooks->free_fn:free; 28 }
构建JSON格式数据,首先调用CJSON_CreateObject()函数,返回一个类型为cJSON_Object的cJSON的结构体,这其中调用了CJSON_CreateNULL()、CJSON_CreateTrue()、…、创建不同类型数据的CJSON结构其。在构建过程中,调用CJSON_New_Item创建对应节点信息;然后调用cJSON_AddItemToObject()并结合不同的对象类型增加节点名称和子节点。然后在其中调用cJSON_AddItemToArray()函数来添加信息,此函数中判断对象孩子结点是否为NULL,如果是NULL,则直接插入,否则找到最后一个孩子,调用suffix_object()函数添加到双向链表的尾部。具体程序如下。
1 // 利用宏函数来快速增加cJSON相关节点信息 2 // 创建一个string值为name的cJSON_Null节点,并添加到object 3 #define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) 4 // 创建一个string值为name的cJSON_True节点,并添加到object 5 #define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) 6 // 创建一个string值为name的cJSON_False节点,并添加到object 7 #define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) 8 // 创建一个string值为name的cJSON_CreateBool节点,并添加到object。b非0为cJSON_True,0为cJSON_False。 9 #define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) 10 // 创建一个string值为name,valuedouble为n,valueint为(int)n的cJSON_Number节点,并添加到object。 11 #define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) 12 // 创建一个string值为name,valuestring为s的cJSON_String节点,并添加到object。 13 #define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) 14 15 // 函数解析 16 // 输入参数无 17 // 返回值:指向一个cJSON_Object类型节点的指针 18 // 创建一个cJSON节点,并设置节点类型无cJSON_Object 19 extern cJSON *cJSON_CreateObject(void); 20 21 cJSON *cJSON_CreateObject(void) 22 { 23 // 创建节点 24 cJSON *item=cJSON_New_Item(); 25 if(item) 26 item->type=cJSON_Object; 27 return item; 28 } 29 30 // 创建value节点 31 static cJSON *cJSON_New_Item(void) 32 { 33 // 分配空间 34 cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); 35 // 分配成功后,初始化为0 36 if (node) memset(node,0,sizeof(cJSON)); 37 return node; 38 } 39 40 // object(cJSON *):被添加节点的节点 41 // string(char *):要添加节点的名称 42 // item(cJSON *):要添加节点 43 // 返回值无 44 // 函数功能:将item节点的名称设置为string。如果object节点没有子节点,就将item设置为object 45 // 子节点,否则将item添加到object->child链表的尾部,成为object->child的兄弟节点 46 extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); 47 48 // 将字符串添加进对象 49 void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) 50 { 51 if (!item) 52 return; 53 if (item->string) 54 cJSON_free(item->string); // 这个儿子之前有key,先清理 55 item->string=cJSON_strdup(string); // 设置key值 56 cJSON_AddItemToArray(object,item); // 添加儿子 57 } 58 59 // 将传入的字符串复制一副本并返回新的字符串指针 60 static char* cJSON_strdup(const char* str) 61 { 62 size_t len; 63 char* copy; 64 65 len = strlen(str) + 1; 66 // 分配空间 67 if (!(copy = (char*)cJSON_malloc(len))) 68 return 0; 69 // 执行复制操作 70 memcpy(copy,str,len); 71 // 返回复制的副本 72 return copy; 73 } 74 75 // 添加节点到object或array中 76 void cJSON_AddItemToArray(cJSON *array, cJSON *item) 77 { 78 cJSON *c=array->child; 79 if (!item) 80 return; 81 if (!c) 82 { 83 array->child=item; // 之前不存在儿子节点,直接添加 84 } 85 else 86 { 87 while (c && c->next) // 先找到最后一个儿子 88 c=c->next; 89 suffix_object(c,item); // 添加儿子,c是item的兄弟节点 90 } 91 } 92 93 // array的处理 94 static void suffix_object(cJSON *prev,cJSON *item) 95 { 96 // 两个兄弟的指针互相指向对方 97 prev->next=item; 98 item->prev=prev; 99 }
JSON解析数据格式时所调用的函数过程如下:
首选,调用cJSON_Parse()函数,此函数是一个二次封装函数,其内部为cJSON_ParseWithOpts()函数,该函数用于提取更多的解析选项,如果需要,最后返回解析结束的位置。而在上面的函数中,调用parse_value()函数进行解析,而该函数首先创建cJSON_NewItem()创建节点,用于存放解析的JSON结构数据,然后根据不同的选项,调用解析函数,其为parse_string(),parse_number(),parse_array(),parse_objec()等。其程序解析如下:
1 // cJSON解析的二次封装函数 2 cJSON *cJSON_Parse(const char *value) 3 { 4 return cJSON_ParseWithOpts(value,0,0); 5 } 6 7 // 解析对象,创建一个新的根并初始化,返回一个cJSON类型 8 cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated) 9 { 10 const char *end=0; 11 cJSON *c=cJSON_New_Item(); 12 ep=0; 13 if (!c) 14 return 0; /* memory fail */ 15 16 end=parse_value(c,skip(value)); 17 if (!end) 18 { 19 cJSON_Delete(c); 20 return 0; 21 } /* parse failure. ep is set. */ 22 23 /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ 24 if (require_null_terminated) 25 { 26 end=skip(end); 27 if (*end) 28 { 29 cJSON_Delete(c); 30 ep=end; 31 return 0; 32 } 33 } 34 if (return_parse_end) 35 *return_parse_end=end; 36 return c; 37 } 38 39 // 解析器核心函数 40 static const char *parse_value(cJSON *item,const char *value) 41 { 42 if (!value) 43 return 0; /* Fail on null. */ 44 if (!strncmp(value,"null",4)) 45 { 46 item->type=cJSON_NULL; 47 return value+4; 48 } 49 if (!strncmp(value,"false",5)) 50 { 51 item->type=cJSON_False; 52 return value+5; 53 } 54 if (!strncmp(value,"true",4)) 55 { 56 item->type=cJSON_True; 57 item->valueint=1; 58 return value+4; 59 } 60 if (*value==‘\"‘) 61 { 62 return parse_string(item,value); 63 } 64 if (*value==‘-‘ || (*value>=‘0‘ && *value<=‘9‘)) 65 { 66 return parse_number(item,value); 67 } 68 if (*value==‘[‘) 69 { 70 return parse_array(item,value); 71 } 72 if (*value==‘{‘) 73 { 74 return parse_object(item,value); 75 } 76 77 ep=value; 78 return 0; /* failure. */ 79 } 80 81 static const char *parse_string(cJSON *item,const char *str) 82 { 83 const char *ptr=str+1; 84 char *ptr2; 85 char *out; 86 int len=0; 87 unsigned uc,uc2; 88 if (*str!=‘\"‘) // 不是字符串情况 89 { 90 ep=str; 91 return 0; 92 } /* not a string! */ 93 94 while (*ptr!=‘\"‘ && *ptr && ++len) 95 if (*ptr++ == ‘\\‘) 96 ptr++; // 跳出前面的引用 97 98 out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ 99 if (!out) 100 return 0; 101 102 ptr=str+1; 103 ptr2=out; 104 while (*ptr!=‘\"‘ && *ptr) 105 { 106 if (*ptr!=‘\\‘) 107 *ptr2++=*ptr++; 108 else 109 { 110 ptr++; 111 switch (*ptr) 112 { 113 case ‘b‘: *ptr2++=‘\b‘; break; 114 case ‘f‘: *ptr2++=‘\f‘; break; 115 case ‘n‘: *ptr2++=‘\n‘; break; 116 case ‘r‘: *ptr2++=‘\r‘; break; 117 case ‘t‘: *ptr2++=‘\t‘; break; 118 case ‘u‘: /* transcode utf16 to utf8. */ 119 uc=parse_hex4(ptr+1); 120 ptr+=4; /* get the unicode char. */ 121 122 if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) 123 break; /* check for invalid. */ 124 125 if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */ 126 { 127 if (ptr[1]!=‘\\‘ || ptr[2]!=‘u‘) 128 break; /* missing second-half of surrogate. */ 129 uc2=parse_hex4(ptr+3);ptr+=6; 130 if (uc2<0xDC00 || uc2>0xDFFF) 131 break; /* invalid second-half of surrogate. */ 132 uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); 133 } 134 135 len=4; 136 if (uc<0x80) 137 len=1; 138 else if (uc<0x800) 139 len=2; 140 else if (uc<0x10000) 141 len=3; 142 ptr2+=len; 143 144 switch (len) 145 { 146 case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 147 case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 148 case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 149 case 1: *--ptr2 =(uc | firstByteMark[len]); 150 } 151 ptr2+=len; 152 break; 153 default: *ptr2++=*ptr; break; 154 } 155 ptr++; 156 } 157 } 158 *ptr2=0; 159 if (*ptr==‘\"‘) ptr++; 160 item->valuestring=out; 161 item->type=cJSON_String; 162 return ptr; 163 } 164 165 // 跳过这些空格 166 static const char *skip(const char *in) 167 { 168 while (in && *in && (unsigned char)*in<=32) 169 in++; 170 return in; 171 } 172 173 // parse_number函数功能:解析数字,对输入的文本生成一个数字,并填充结果项,传入参数有两 174 // 个,这里先只关注num,返回值是一个字符串 175 static const char *parse_number(cJSON *item,const char *num) 176 { 177 double n=0,sign=1,scale=0; 178 int subscale=0,signsubscale=1; 179 180 if (*num==‘-‘) sign=-1,num++; // 判断数字是否是有符号数字 181 if (*num==‘0‘) num++; // 判断数字是否为0 182 if (*num>=‘1‘ && *num<=‘9‘) 183 do // 转换数字 184 n=(n*10.0)+(*num++ -‘0‘); 185 while (*num>=‘0‘ && *num<=‘9‘); 186 if (*num==‘.‘ && num[1]>=‘0‘ && num[1]<=‘9‘) // 对小数点后边的部分进行处理,scale记录小数点后边的位数 187 { 188 num++; 189 do 190 n=(n*10.0)+(*num++ -‘0‘),scale--; // scale为小数点后的位数 191 while (*num>=‘0‘ && *num<=‘9‘); 192 } 193 if (*num==‘e‘ || *num==‘E‘) // 是否为指数,科学计数法 194 { 195 num++; 196 if (*num==‘+‘) // 判断指数后边幂的正负号 197 num++; 198 else if (*num==‘-‘) 199 signsubscale=-1,num++; 200 while (*num>=‘0‘ && *num<=‘9‘) // 处理指数后边10的幂 201 subscale=(subscale*10)+(*num++ - ‘0‘); 202 } 203 // 将字符串转换为相应的数值 204 n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ 205 206 item->valuedouble=n; // 将算出来的值存入缓存 207 item->valueint=(int)n; // 将算出来的值存入缓存 208 item->type=cJSON_Number; // 目标类型为数字 209 return num; 210 } 211 212 // 从输入文本中构建array 213 static const char *parse_array(cJSON *item,const char *value) 214 { 215 cJSON *child; 216 if (*value!=‘[‘) {ep=value;return 0;} /* not an array! */ 217 218 item->type=cJSON_Array; 219 value=skip(value+1); 220 if (*value==‘]‘) return value+1; /* empty array. */ 221 222 item->child=child=cJSON_New_Item(); 223 if (!item->child) return 0; /* memory fail */ 224 value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ 225 if (!value) return 0; 226 227 while (*value==‘,‘) 228 { 229 cJSON *new_item; 230 if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ 231 child->next=new_item;new_item->prev=child;child=new_item; 232 value=skip(parse_value(child,skip(value+1))); 233 if (!value) return 0; /* memory fail */ 234 } 235 236 if (*value==‘]‘) return value+1; /* end of array */ 237 ep=value;return 0; /* malformed. */ 238 } 239 240 // 从输入文本中构建object 241 static const char *parse_object(cJSON *item,const char *value) 242 { 243 cJSON *child; 244 if (*value!=‘{‘) {ep=value;return 0;} /* not an object! */ 245 246 item->type=cJSON_Object; 247 value=skip(value+1); 248 if (*value==‘}‘) return value+1; /* empty array. */ 249 250 item->child=child=cJSON_New_Item(); 251 if (!item->child) return 0; 252 value=skip(parse_string(child,skip(value))); 253 if (!value) return 0; 254 child->string=child->valuestring;child->valuestring=0; 255 if (*value!=‘:‘) {ep=value;return 0;} /* fail! */ 256 value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ 257 if (!value) return 0; 258 259 while (*value==‘,‘) 260 { 261 cJSON *new_item; 262 if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ 263 child->next=new_item;new_item->prev=child;child=new_item; 264 value=skip(parse_string(child,skip(value+1))); 265 if (!value) return 0; 266 child->string=child->valuestring;child->valuestring=0; 267 if (*value!=‘:‘) {ep=value;return 0;} /* fail! */ 268 value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ 269 if (!value) return 0; 270 } 271 272 if (*value==‘}‘) return value+1; /* end of array */ 273 ep=value;return 0; /* malformed. */ 274 } 275 276 // 将十六进制的字符串转换为数字表示! 277 static unsigned parse_hex4(const char *str) 278 { 279 unsigned h=0; 280 if (*str>=‘0‘ && *str<=‘9‘) 281 h+=(*str)-‘0‘; 282 else if (*str>=‘A‘ && *str<=‘F‘) 283 h+=10+(*str)-‘A‘; 284 else if (*str>=‘a‘ && *str<=‘f‘) 285 h+=10+(*str)-‘a‘; 286 else 287 return 0; 288 h=h<<4;str++; 289 if (*str>=‘0‘ && *str<=‘9‘) 290 h+=(*str)-‘0‘; 291 else if (*str>=‘A‘ && *str<=‘F‘) 292 h+=10+(*str)-‘A‘; 293 else if (*str>=‘a‘ && *str<=‘f‘) 294 h+=10+(*str)-‘a‘; 295 else 296 return 0; 297 h=h<<4;str++; 298 if (*str>=‘0‘ && *str<=‘9‘) 299 h+=(*str)-‘0‘; 300 else if (*str>=‘A‘ && *str<=‘F‘) 301 h+=10+(*str)-‘A‘; 302 else if (*str>=‘a‘ && *str<=‘f‘) 303 h+=10+(*str)-‘a‘; 304 else 305 return 0; 306 h=h<<4;str++; 307 if (*str>=‘0‘ && *str<=‘9‘) 308 h+=(*str)-‘0‘; 309 else if (*str>=‘A‘ && *str<=‘F‘) 310 h+=10+(*str)-‘A‘; 311 else if (*str>=‘a‘ && *str<=‘f‘) 312 h+=10+(*str)-‘a‘; 313 else 314 return 0; 315 return h; 316 } 317 318 打印JSON信息 319 320 // 打印值到文本 321 static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p) 322 { 323 char *out=0; 324 if (!item) return 0; 325 if (p) 326 { 327 switch ((item->type)&255) 328 { 329 case cJSON_NULL: {out=ensure(p,5); if (out) strcpy(out,"null"); break;} 330 case cJSON_False: {out=ensure(p,6); if (out) strcpy(out,"false"); break;} 331 case cJSON_True: {out=ensure(p,5); if (out) strcpy(out,"true"); break;} 332 case cJSON_Number: out=print_number(item,p);break; 333 case cJSON_String: out=print_string(item,p);break; 334 case cJSON_Array: out=print_array(item,depth,fmt,p);break; 335 case cJSON_Object: out=print_object(item,depth,fmt,p);break; 336 } 337 } 338 else 339 { 340 switch ((item->type)&255) 341 { 342 case cJSON_NULL: out=cJSON_strdup("null"); break; 343 case cJSON_False: out=cJSON_strdup("false");break; 344 case cJSON_True: out=cJSON_strdup("true"); break; 345 case cJSON_Number: out=print_number(item,0);break; 346 case cJSON_String: out=print_string(item,0);break; 347 case cJSON_Array: out=print_array(item,depth,fmt,0);break; 348 case cJSON_Object: out=print_object(item,depth,fmt,0);break; 349 } 350 } 351 return out; 352 } 353 354 // 打印array到文本 355 static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p) 356 { 357 char **entries; 358 char *out=0,*ptr,*ret;int len=5; 359 cJSON *child=item->child; 360 int numentries=0,i=0,fail=0; 361 size_t tmplen=0; 362 363 /* How many entries in the array? */ 364 while (child) numentries++,child=child->next; 365 /* Explicitly handle numentries==0 */ 366 if (!numentries) 367 { 368 if (p) out=ensure(p,3); 369 else out=(char*)cJSON_malloc(3); 370 if (out) strcpy(out,"[]"); 371 return out; 372 } 373 374 if (p) 375 { 376 /* Compose the output array. */ 377 i=p->offset; 378 ptr=ensure(p,1);if (!ptr) return 0; *ptr=‘[‘; p->offset++; 379 child=item->child; 380 while (child && !fail) 381 { 382 print_value(child,depth+1,fmt,p); 383 p->offset=update(p); 384 if (child->next) {len=fmt?2:1;ptr=ensure(p,len+1);if (!ptr) return 0;*ptr++=‘,‘;if(fmt)*ptr++=‘ ‘;*ptr=0;p->offset+=len;} 385 child=child->next; 386 } 387 ptr=ensure(p,2);if (!ptr) return 0; *ptr++=‘]‘;*ptr=0; 388 out=(p->buffer)+i; 389 } 390 else 391 { 392 /* Allocate an array to hold the values for each */ 393 entries=(char**)cJSON_malloc(numentries*sizeof(char*)); 394 if (!entries) return 0; 395 memset(entries,0,numentries*sizeof(char*)); 396 /* Retrieve all the results: */ 397 child=item->child; 398 while (child && !fail) 399 { 400 ret=print_value(child,depth+1,fmt,0); 401 entries[i++]=ret; 402 if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1; 403 child=child->next; 404 } 405 406 /* If we didn‘t fail, try to malloc the output string */ 407 if (!fail) out=(char*)cJSON_malloc(len); 408 /* If that fails, we fail. */ 409 if (!out) fail=1; 410 411 /* Handle failure. */ 412 if (fail) 413 { 414 for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]); 415 cJSON_free(entries); 416 return 0; 417 } 418 419 /* Compose the output array. */ 420 *out=‘[‘; 421 ptr=out+1;*ptr=0; 422 for (i=0;i<numentries;i++) 423 { 424 tmplen=strlen(entries[i]);memcpy(ptr,entries[i],tmplen);ptr+=tmplen; 425 if (i!=numentries-1) {*ptr++=‘,‘;if(fmt)*ptr++=‘ ‘;*ptr=0;} 426 cJSON_free(entries[i]); 427 } 428 cJSON_free(entries); 429 *ptr++=‘]‘;*ptr++=0; 430 } 431 return out; 432 } 433 434 // 打印object到文本中 435 static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p) 436 { 437 char **entries=0,**names=0; 438 char *out=0,*ptr,*ret,*str;int len=7,i=0,j; 439 cJSON *child=item->child; 440 int numentries=0,fail=0; 441 size_t tmplen=0; 442 /* Count the number of entries. */ 443 while (child) numentries++,child=child->next; 444 /* Explicitly handle empty object case */ 445 if (!numentries) 446 { 447 if (p) out=ensure(p,fmt?depth+4:3); 448 else out=(char*)cJSON_malloc(fmt?depth+4:3); 449 if (!out) return 0; 450 ptr=out;*ptr++=‘{‘; 451 if (fmt) {*ptr++=‘\n‘;for (i=0;i<depth-1;i++) *ptr++=‘\t‘;} 452 *ptr++=‘}‘;*ptr++=0; 453 return out; 454 } 455 if (p) 456 { 457 /* Compose the output: */ 458 i=p->offset; 459 len=fmt?2:1; ptr=ensure(p,len+1); if (!ptr) return 0; 460 *ptr++=‘{‘; if (fmt) *ptr++=‘\n‘; *ptr=0; p->offset+=len; 461 child=item->child;depth++; 462 while (child) 463 { 464 if (fmt) 465 { 466 ptr=ensure(p,depth); if (!ptr) return 0; 467 for (j=0;j<depth;j++) *ptr++=‘\t‘; 468 p->offset+=depth; 469 } 470 print_string_ptr(child->string,p); 471 p->offset=update(p); 472 473 len=fmt?2:1; 474 ptr=ensure(p,len); if (!ptr) return 0; 475 *ptr++=‘:‘;if (fmt) *ptr++=‘\t‘; 476 p->offset+=len; 477 478 print_value(child,depth,fmt,p); 479 p->offset=update(p); 480 481 len=(fmt?1:0)+(child->next?1:0); 482 ptr=ensure(p,len+1); if (!ptr) return 0; 483 if (child->next) *ptr++=‘,‘; 484 if (fmt) *ptr++=‘\n‘;*ptr=0; 485 p->offset+=len; 486 child=child->next; 487 } 488 ptr=ensure(p,fmt?(depth+1):2); if (!ptr) return 0; 489 if (fmt) for (i=0;i<depth-1;i++) *ptr++=‘\t‘; 490 *ptr++=‘}‘;*ptr=0; 491 out=(p->buffer)+i; 492 } 493 else 494 { 495 /* Allocate space for the names and the objects */ 496 entries=(char**)cJSON_malloc(numentries*sizeof(char*)); 497 if (!entries) return 0; 498 names=(char**)cJSON_malloc(numentries*sizeof(char*)); 499 if (!names) {cJSON_free(entries);return 0;} 500 memset(entries,0,sizeof(char*)*numentries); 501 memset(names,0,sizeof(char*)*numentries); 502 503 /* Collect all the results into our arrays: */ 504 child=item->child;depth++;if (fmt) len+=depth; 505 while (child) 506 { 507 names[i]=str=print_string_ptr(child->string,0); 508 entries[i++]=ret=print_value(child,depth,fmt,0); 509 if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1; 510 child=child->next; 511 } 512 513 /* Try to allocate the output string */ 514 if (!fail) out=(char*)cJSON_malloc(len); 515 if (!out) fail=1; 516 517 /* Handle failure */ 518 if (fail) 519 { 520 for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);} 521 cJSON_free(names);cJSON_free(entries); 522 return 0; 523 } 524 525 /* Compose the output: */ 526 *out=‘{‘;ptr=out+1;if (fmt)*ptr++=‘\n‘;*ptr=0; 527 for (i=0;i<numentries;i++) 528 { 529 if (fmt) for (j=0;j<depth;j++) *ptr++=‘\t‘; 530 tmplen=strlen(names[i]);memcpy(ptr,names[i],tmplen);ptr+=tmplen; 531 *ptr++=‘:‘;if (fmt) *ptr++=‘\t‘; 532 strcpy(ptr,entries[i]);ptr+=strlen(entries[i]); 533 if (i!=numentries-1) *ptr++=‘,‘; 534 if (fmt) *ptr++=‘\n‘;*ptr=0; 535 cJSON_free(names[i]);cJSON_free(entries[i]); 536 } 537 538 cJSON_free(names);cJSON_free(entries); 539 if (fmt) for (i=0;i<depth-1;i++) *ptr++=‘\t‘; 540 *ptr++=‘}‘;*ptr++=0; 541 } 542 return out; 543 }
其余函数信息如下:
1 // 返回节点的个数 2 int cJSON_GetArraySize(cJSON *array) 3 { 4 cJSON *c=array->child; 5 int i=0; 6 while(c) 7 i++,c=c->next; 8 return i; 9 } 10 // 返回array中第item个节点的地址 11 cJSON *cJSON_GetArrayItem(cJSON *array,int item) 12 { 13 cJSON *c=array->child; 14 while (c && item>0) 15 item--,c=c->next; 16 return c; 17 } 18 // 返回Object中第item个节点的地址 19 cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) 20 { 21 cJSON *c=object->child; 22 while (c && cJSON_strcasecmp(c->string,string)) 23 c=c->next; 24 return c; 25 } 26 27 // 在链表中插入一个新的节点 28 void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem) 29 { 30 cJSON *c=array->child; 31 // 找到which位置 32 while (c && which>0) 33 c=c->next,which--; 34 // 添加新的节点到array中 35 if (!c) 36 { 37 cJSON_AddItemToArray(array,newitem); 38 return; 39 } 40 // 将链表节点进行挂接 41 newitem->next=c; 42 newitem->prev=c->prev; 43 c->prev=newitem; 44 // 处理arrya的孩子节点 45 if (c==array->child) 46 array->child=newitem; 47 else 48 newitem->prev->next=newitem; 49 } 50 // 替换节点操作,用新的节点替换原有的某一个节点 51 void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) 52 { 53 cJSON *c=array->child; 54 // 找到which位置 55 while (c && which>0) 56 c=c->next,which--; 57 if (!c) 58 return; 59 // 进行挂接 60 newitem->next=c->next; 61 newitem->prev=c->prev; 62 // 处理NULL情况 63 if (newitem->next) 64 newitem->next->prev=newitem; 65 // 处理孩子节点 66 if (c==array->child) 67 array->child=newitem; 68 else 69 newitem->prev->next=newitem; 70 c->next=c->prev=0; 71 // 删除替换的节点 72 cJSON_Delete(c); 73 } 74 // 替换节点操作 75 // 用原有节点替换现有节点 76 void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem) 77 { 78 int i=0; 79 cJSON *c=object->child; 80 while(c && cJSON_strcasecmp(c->string,string)) 81 i++,c=c->next; 82 if(c) 83 { 84 newitem->string=cJSON_strdup(string); 85 cJSON_ReplaceItemInArray(object,i,newitem); 86 } 87 } 88 89 /* Create basic types: */ 90 // 创建基本类型函数 91 cJSON *cJSON_CreateNull(void) 92 { 93 cJSON *item=cJSON_New_Item(); 94 if(item) 95 item->type=cJSON_NULL; 96 return item; 97 } 98 cJSON *cJSON_CreateTrue(void) 99 { 100 cJSON *item=cJSON_New_Item(); 101 if(item) 102 item->type=cJSON_True; 103 return item; 104 } 105 cJSON *cJSON_CreateFalse(void) 106 { 107 cJSON *item=cJSON_New_Item(); 108 if(item) 109 item->type=cJSON_False; 110 return item; 111 } 112 cJSON *cJSON_CreateBool(int b) 113 { 114 cJSON *item=cJSON_New_Item(); 115 if(item) 116 item->type=b?cJSON_True:cJSON_False; 117 return item; 118 } 119 cJSON *cJSON_CreateNumber(double num) 120 { 121 cJSON *item=cJSON_New_Item(); 122 if(item) 123 { 124 item->type=cJSON_Number; 125 item->valuedouble=num; 126 item->valueint=(int)num; 127 } 128 return item; 129 } 130 cJSON *cJSON_CreateString(const char *string) 131 { 132 cJSON *item=cJSON_New_Item(); 133 if(item) 134 { 135 item->type=cJSON_String; 136 item->valuestring=cJSON_strdup(string); 137 } 138 return item; 139 } 140 cJSON *cJSON_CreateArray(void) 141 { 142 cJSON *item=cJSON_New_Item(); 143 if(item) 144 item->type=cJSON_Array; 145 return item; 146 } 147 cJSON *cJSON_CreateObject(void) 148 { 149 cJSON *item=cJSON_New_Item(); 150 if(item) 151 item->type=cJSON_Object; 152 return item; 153 } 154 155 /* Create Arrays: */ 156 // 创建array 157 cJSON *cJSON_CreateIntArray(const int *numbers,int count) 158 { 159 int i; 160 cJSON *n=0,*p=0,*a=cJSON_CreateArray(); 161 for(i=0;a && i<count;i++) 162 { 163 n=cJSON_CreateNumber(numbers[i]); 164 if(!i) 165 a->child=n; 166 else 167 suffix_object(p,n); 168 p=n; 169 } 170 return a; 171 } 172 cJSON *cJSON_CreateFloatArray(const float *numbers,int count) 173 { 174 int i; 175 cJSON *n=0,*p=0,*a=cJSON_CreateArray(); 176 for(i=0;a && i<count;i++) 177 { 178 n=cJSON_CreateNumber(numbers[i]); 179 if(!i) 180 a->child=n; 181 else 182 suffix_object(p,n); 183 p=n; 184 } 185 return a; 186 } 187 cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) 188 { 189 int i; 190 cJSON *n=0,*p=0,*a=cJSON_CreateArray(); 191 for(i=0;a && i<count;i++) 192 { 193 n=cJSON_CreateNumber(numbers[i]); 194 if(!i) 195 a->child=n; 196 else 197 suffix_object(p,n); 198 p=n; 199 } 200 return a; 201 } 202 cJSON *cJSON_CreateStringArray(const char **strings,int count) 203 { 204 int i; 205 cJSON *n=0,*p=0,*a=cJSON_CreateArray(); 206 for(i=0;a && i<count;i++) 207 { 208 n=cJSON_CreateString(strings[i]); 209 if(!i) 210 a->child=n; 211 else 212 suffix_object(p,n); 213 p=n; 214 } 215 return a; 216 } 217 218 /* Duplication */ 219 // 拷贝副本操作 220 cJSON *cJSON_Duplicate(cJSON *item,int recurse) 221 { 222 cJSON *newitem,*cptr,*nptr=0,*newchild; 223 /* Bail on bad ptr */ 224 if (!item) 225 return 0; 226 /* Create new item */ 227 newitem=cJSON_New_Item(); 228 if (!newitem) 229 return 0; 230 /* Copy over all vars */ 231 newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble; 232 if (item->valuestring) 233 { 234 newitem->valuestring=cJSON_strdup(item->valuestring); 235 if (!newitem->valuestring) 236 { 237 cJSON_Delete(newitem); 238 return 0; 239 } 240 } 241 if (item->string) 242 { 243 newitem->string=cJSON_strdup(item->string); 244 if (!newitem->string) 245 { 246 cJSON_Delete(newitem); 247 return 0; 248 } 249 } 250 /* If non-recursive, then we‘re done! */ 251 if (!recurse) 252 return newitem; 253 /* Walk the ->next chain for the child. */ 254 cptr=item->child; 255 while (cptr) 256 { 257 newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */ 258 if (!newchild) 259 { 260 cJSON_Delete(newitem); 261 return 0; 262 } 263 if (nptr) 264 { 265 nptr->next=newchild,newchild->prev=nptr; 266 nptr=newchild; 267 } /* If newitem->child already set, then crosswire ->prev and ->next and move on */ 268 else 269 { 270 newitem->child=newchild; 271 nptr=newchild; 272 } /* Set newitem->child and move to it */ 273 cptr=cptr->next; 274 } 275 return newitem; 276 } 277 278 void cJSON_Minify(char *json) 279 { 280 char *into=json; 281 while (*json) 282 { 283 if (*json==‘ ‘) json++; 284 else if (*json==‘\t‘) json++; /* Whitespace characters. */ 285 else if (*json==‘\r‘) json++; 286 else if (*json==‘\n‘) json++; 287 else if (*json==‘/‘ && json[1]==‘/‘) while (*json && *json!=‘\n‘) json++; /* double-slash comments, to end of line. */ 288 else if (*json==‘/‘ && json[1]==‘*‘) {while (*json && !(*json==‘*‘ && json[1]==‘/‘)) json++;json+=2;} /* multiline comments. */ 289 else if (*json==‘\"‘){*into++=*json++;while (*json && *json!=‘\"‘){if (*json==‘\\‘) *into++=*json++;*into++=*json++;}*into++=*json++;} /* string literals, which are \" sensitive. */ 290 else *into++=*json++; /* All other characters. */ 291 } 292 *into=0; /* and null-terminate. */ 293 }
-
参考文献
http://www.0xffffff.org/2014/02/10/29-cjson-analyse/
http://github.tiankonguse.com/blog/2014/12/18/cjson-source.html