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;
}
 

 

posted @ 2021-02-26 21:19  ^super^  阅读(260)  评论(0)    收藏  举报