源码获取
git clone https://github.com/DaveGamble/cJSON.git
cJSON数据结构
- cJSON结构体
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
//next和prev两个指针提供了一个cJSON节点指向双向链表的前一个节点或者后一个节点
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
//child指针指向当前cJSON节点的子节点
struct cJSON *child;
/* The type of the item, as above. */
//cJSON节点的类型
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
//cJSON节点的key值
char *string;
} cJSON;
- cJSON类型
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
//raw类型 {"message":"\{\"name\":\"Tom\"\}"}
#define cJSON_Raw (1 << 7) /* raw json */
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512
对于各个类型的判断有专门的函数类似:cJSON_Is...,例如:
cJSON_bool cJSON_IsString(const cJSON * const item)
{
if (item == NULL)
{
return false;
}
return (item->type & 0xFF) == cJSON_String;
}
创建cJSON节点,使用类似cJSON_Create...的函数分配内存,例如:
//定义的宏
#define internal_malloc malloc
#define internal_free free
#define internal_realloc realloc
//cJSON中封装了一层分配和释放内存时使用的函数
typedef struct internal_hooks
{
void *(CJSON_CDECL *allocate)(size_t size);
void (CJSON_CDECL *deallocate)(void *pointer);
void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
} internal_hooks;
//初始化global_hooks变量,实际上就是调用了c语言的malloc,free,realloc三个函数
static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
//分配一个cJSON结构体大小的内存空间
static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
{
cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
if (node)
{
memset(node, '\0', sizeof(cJSON));
}
return node;
}
//以创建True类型的子节点为例,其他类型的cJSON节点创建非常的类似
cJSON * cJSON_CreateTrue(void)
{
//获取到分配的内存地址
cJSON *item = cJSON_New_Item(&global_hooks);
if(item)
{
//将type赋予对应的类型
item->type = cJSON_True;
}
return item;
}
cJSON结构体内存释放
void cJSON_Delete(cJSON *item)
{
cJSON *next = NULL;
//如果不是NULL指针
while (item != NULL)
{
//保存下一个节点
next = item->next;
//如果不是Reference类型,子节点不为空
if (!(item->type & cJSON_IsReference) && (item->child != NULL))
{
//递归释放子节点
cJSON_Delete(item->child);
}
//如果不是Reference类型,有分配valuestring指针的空间
if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
{
//释放valuestring的内存
global_hooks.deallocate(item->valuestring);
}
//如果不是cJSON_StringIsConst,则将cJSON结构体中的string释放
if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
{
global_hooks.deallocate(item->string);
}
global_hooks.deallocate(item);
//释放下一个兄弟节点
item = next;
}
}
数组 Arrays
- 向数组中添加元素
//发布给用户的接口
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
{
//调用静态函数来实现,array:数组,item:要插入的元素
add_item_to_array(array, item);
}
//内部静态函数,用户无法调用
static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
{
cJSON *child = NULL;
//对于指针的合法性校验
if ((item == NULL) || (array == NULL))
{
return false;
}
//获取到数组的子节点值
child = array->child;
//如果没有子节点,则新加入的元素是子节点的第一项
if (child == NULL)
{
/* list is empty, start new one */
array->child = item;
}
//如果存在子节点,则将新插入的节点放到子节点的最后面。
else
{
/* append to the end */
while (child->next)
{
child = child->next;
}
//suffix_object函数实现的功能:
//child->next=item;
//item->prev=child;
suffix_object(child, item);
}
return true;
}
向数组中的特定位置插入元素
void cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
{
cJSON *after_inserted = NULL;
//判断which是否合法
if (which < 0)
{
return;
}
//get_array_item函数用来获取到第which个元素的指针(从0开始),实现起来很简单,这里略过
after_inserted = get_array_item(array, (size_t)which);
//如果是数组中没有元素
if (after_inserted == NULL)
{
add_item_to_array(array, newitem);
return;
}
//双向链表的插入元素过程
newitem->next = after_inserted;
newitem->prev = after_inserted->prev;
after_inserted->prev = newitem;
//如果是插入到最开始地方,将数组的child指针指向新加入的元素
if (after_inserted == array->child)
{
array->child = newitem;
}
//如果不是在数组最开始的地方
else
{
newitem->prev->next = newitem;
}
}
- 获取到指定位置元素
//将在数组which位置的元素从数组中分离出来
cJSON * cJSON_DetachItemFromArray(cJSON *array, int which)
{
if (which < 0)
{
return NULL;
}
return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
}
//实际上就是从双向链表中将元素分离出来
cJSON * cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
{
if ((parent == NULL) || (item == NULL))
{
return NULL;
}
if (item->prev != NULL)
{
/* not the first element */
item->prev->next = item->next;
}
if (item->next != NULL)
{
/* not the last element */
item->next->prev = item->prev;
}
if (item == parent->child)
{
/* first element */
parent->child = item->next;
}
/* make sure the detached item doesn't point anywhere anymore */
item->prev = NULL;
item->next = NULL;
return item;
}
- 删除数组中特定位置的元素项
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
{
//调用了cJSON_DetachItemFromArray函数将要删除的项从数组中分离出来
cJSON_Delete(cJSON_DetachItemFromArray(array, which));
}
- 将数组中特定元素替换掉
void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
{
if (which < 0)
{
return;
}
cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
}
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
{
if ((parent == NULL) || (replacement == NULL) || (item == NULL))
{
return false;
}
//如果要替换的节点和新节点是同一个
if (replacement == item)
{
return true;
}
replacement->next = item->next;
replacement->prev = item->prev;
if (replacement->next != NULL)
{
replacement->next->prev = replacement;
}
if (replacement->prev != NULL)
{
replacement->prev->next = replacement;
}
if (parent->child == item)
{
parent->child = replacement;
}
item->next = NULL;
item->prev = NULL;
//将旧的节点删除
cJSON_Delete(item);
return true;
}
- 获取数组的大小
int cJSON_GetArraySize(const cJSON *array)
{
cJSON *child = NULL;
size_t size = 0;
if (array == NULL)
{
return 0;
}
//获取到child子节点
child = array->child;
while(child != NULL)
{
size++;
child = child->next;
}
/* FIXME: Can overflow here. Cannot be fixed without breaking the API */
return (int)size;
}
Object对象
- 向对象中添加一个元素项
void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
{
add_item_to_object(object, string, item, &global_hooks, false);
}
static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)
{
char *new_key = NULL;
int new_type = cJSON_Invalid;
if ((object == NULL) || (string == NULL) || (item == NULL))
{
return false;
}
if (constant_key)
{
//将string的const指针去掉
new_key = (char*)cast_away_const(string);
new_type = item->type | cJSON_StringIsConst;
}
else
{
//cJSON_strdup创建一个string字符串的副本,并返回新分配内存的地址
new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
if (new_key == NULL)
{
return false;
}
new_type = item->type & ~cJSON_StringIsConst;
}
if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
{
hooks->deallocate(item->string);
}
item->string = new_key;
item->type = new_type;
return add_item_to_array(object, item);
}
未完
关于json的解析和序列化放到后面的文章中
2019年6月23日