JSON源码分析(第二部分)
一、JSON简介
JSON数据结构
(1)JSON的数据结构只有两种:Object是以{}表示,Array是以[ ]表示;
(2)可以相互嵌套表示,不同语言之中的对象、记录、结构、字典、哈希表等都可以作为转换的对象基础结构。
JSON数据表示如下:
{ "language": "C", "C": {"优点": "简洁紧凑、灵活方便、功能强大", "缺点": "危险性高、开发周期长"} }
二、CJSON的数据结构和函数
CJSON设计的核心是采用了双向链表;其储存结构有点像广义表。
1. cJSON的结构体定义
typedef struct cJSON { struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ int type; /* The type of the item, as above. */ char *valuestring; /* The item's string, if type==cJSON_String */ int valueint; /* The item's number, if type==cJSON_Number */ double valuedouble; /* The item's number, if type==cJSON_Number */ char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ } cJSON;
成员变量type包括:cJSON_False 、cJSON_True 、cJSON_NULL 、cJSON_Number 、 cJSON_String 、cJSON_Array 、cJSON_Object
2.创建空节点
static cJSON *cJSON_New_Item(void) { cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); if (node) memset(node,0,sizeof(cJSON)); return node; }
3.创建相应的节点type
cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item; cJSON *cJSON_CreateNumber(double num){ cJSON *item=cJSON_New_Item(); if(item){ item->type=cJSON_Number; item->valuedouble=num; item->valueint=(int)num; } return item; } cJSON *cJSON_CreateString(const char *string){ cJSON *item=cJSON_New_Item(); if(item){ item->type=cJSON_String; item->valuestring=cJSON_strdup(string); } return item; } cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
4.创建节点数组
cJSON *cJSON_CreateIntArray(const int *numbers,int count){ int i; cJSON *n=0,*p=0,*a=cJSON_CreateArray(); for(i=0;a && i<count;i++){ n=cJSON_CreateNumber(numbers[i]); if(!i)a->child=n;//数组节点的孩子节点是数组第一个元素 else suffix_object(p,n); //static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} p=n; } return a; } cJSON *cJSON_CreateFloatArray(const float *numbers,int count){int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} cJSON *cJSON_CreateDoubleArray(const double *numbers,int count){int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} cJSON *cJSON_CreateStringArray(const char **strings,int count){ int i; cJSON *n=0,*p=0,*a=cJSON_CreateArray(); for(i=0;a && i<count;i++){ n=cJSON_CreateString(strings[i]); if(!i)a->child=n; else suffix_object(p,n); p=n; } return a; }
5.添加孩子节点到Array、Object上
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) #define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) #define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) #define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) #define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) #define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item){ if (!item) return; if (item->string) cJSON_free(item->string); item->string=cJSON_strdup(string); cJSON_AddItemToArray(object,item);//将item添加到object数组上 } void cJSON_AddItemToArray(cJSON *array, cJSON *item){ cJSON *c=array->child; if (!item) return; if (!c) {array->child=item;}//如果array没有孩子,item是其第一个孩子 else { while (c && c->next) c=c->next; //如果array有孩子,将item插入到数组末尾 //static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} suffix_object(c,item); } } void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item){ if (!item) return; if (!(item->type&cJSON_StringIsConst) && item->string) cJSON_free(item->string); item->string=(char*)string; item->type|=cJSON_StringIsConst; cJSON_AddItemToArray(object,item); }
6.创建引用节点
static cJSON *create_reference(cJSON *item){ cJSON *ref=cJSON_New_Item(); if (!ref) return 0; memcpy(ref,item,sizeof(cJSON)); ref->string=0; ref->type|=cJSON_IsReference; ref->next=ref->prev=0; return ref; }
7.添加引用节点到Array、Object上
void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item){ cJSON_AddItemToArray(array,create_reference(item)); } void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item){ cJSON_AddItemToObject(object,string,create_reference(item)); }
8.获取Array、Object
int cJSON_GetArraySize(cJSON *array){ cJSON *c=array->child; int i=0; while(c)i++,c=c->next; return i; } cJSON *cJSON_GetArrayItem(cJSON *array,int item){ cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c; } cJSON *cJSON_GetObjectItem(cJSON *object,const char *string){ cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c; }
9.插入/替换节点
void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem){ cJSON *c=array->child; while (c && which>0) c=c->next,which--; if (!c) { cJSON_AddItemToArray(array,newitem); return; } newitem->next=c; newitem->prev=c->prev; c->prev=newitem; if (c==array->child) array->child=newitem; else newitem->prev->next=newitem; } void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem){ cJSON *c=array->child; while (c && which>0) c=c->next,which--; if (!c) return; newitem->next=c->next; newitem->prev=c->prev; if (newitem->next) newitem->next->prev=newitem; if (c==array->child) array->child=newitem; else newitem->prev->next=newitem; c->next=c->prev=0; cJSON_Delete(c); } void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){ int i=0; cJSON *c=object->child; while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next; if(c){ newitem->string=cJSON_strdup(string); cJSON_ReplaceItemInArray(object,i,newitem); } }
10.删除孩子节点
cJSON *cJSON_DetachItemFromArray(cJSON *array,int which){ cJSON *c=array->child; while (c && which>0) c=c->next,which--; if (!c) return 0; if (c->prev) c->prev->next=c->next; if (c->next) c->next->prev=c->prev; if (c==array->child) array->child=c->next; c->prev=c->next=0; return c; } void cJSON_DeleteItemFromArray(cJSON *array,int which){ cJSON_Delete(cJSON_DetachItemFromArray(array,which)); } cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string){ int i=0; cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next; if (c) return cJSON_DetachItemFromArray(object,i); return 0; } void cJSON_DeleteItemFromObject(cJSON *object,const char *string){ cJSON_Delete(cJSON_DetachItemFromObject(object,string)); }
11.层次树的解析、解析后的JSON格式数据再还原成JSON格式数据打印、最后删除。这里不贴代码了,函数的调用如图

12.其他函数
//字符串比较函数(不区分大小写),相同返回0,大于返回正值,小于返回负值 static int cJSON_strcasecmp(const char *s1,const char *s2) { if (!s1) return (s1==s2)?0:1;if (!s2) return 1; for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); } //深拷贝,根据str创建了一份拷贝 static char* cJSON_strdup(const char* str) { size_t len; char* copy; len = strlen(str) + 1; if (!(copy = (char*)cJSON_malloc(len))) return 0; memcpy(copy,str,len); return copy; } //使用自定义内存分配函数,或者是系统内存分配函数,默认是malloc和free void cJSON_InitHooks(cJSON_Hooks* hooks) { if (!hooks) { /* Reset hooks */ cJSON_malloc = malloc; cJSON_free = free; return; } cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; cJSON_free = (hooks->free_fn)?hooks->free_fn:free; } //返回比x大的最小的2的N次方数 static int pow2gt (int x) { --x; x|=x>>1; x|=x>>2; x|=x>>4; x|=x>>8; x|=x>>16; return x+1; } typedef struct {char *buffer; int length; int offset; } printbuffer; //确保读取的大小在字符串的范围内; 如果需要的大小在总长度内,直接范围偏移地址;如果不够,则使用Pow2gt先申请更大的一块 //,复制内容后,释放原来的内存,再返回偏移值; static char* ensure(printbuffer *p,int needed) { char *newbuffer;int newsize; if (!p || !p->buffer) return 0; needed+=p->offset; if (needed<=p->length) return p->buffer+p->offset; newsize=pow2gt(needed); newbuffer=(char*)cJSON_malloc(newsize); if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;} if (newbuffer) memcpy(newbuffer,p->buffer,p->length); cJSON_free(p->buffer); p->length=newsize; p->buffer=newbuffer; return newbuffer+p->offset; } static int update(printbuffer *p) { char *str; if (!p || !p->buffer) return 0; str=p->buffer+p->offset; return p->offset+strlen(str); } //将字符串转换成16进制格式 static unsigned parse_hex4(const char *str) { unsigned h=0; if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; h=h<<4;str++; if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; h=h<<4;str++; if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; h=h<<4;str++; if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; return h; } //跳过控制字符,asc码小于33,包括\r\n static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} //双向链表节点互指 static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} cJSON *cJSON_Duplicate(cJSON *item,int recurse) { cJSON *newitem,*cptr,*nptr=0,*newchild; /* Bail on bad ptr */ if (!item) return 0; /* Create new item */ newitem=cJSON_New_Item(); if (!newitem) return 0; /* Copy over all vars */ newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble; if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}} if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}} /* If non-recursive, then we're done! */ if (!recurse) return newitem; /* Walk the ->next chain for the child. */ cptr=item->child; while (cptr) { newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */ if (!newchild) {cJSON_Delete(newitem);return 0;} if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */ else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */ cptr=cptr->next; } return newitem; }

浙公网安备 33010602011771号