类型判断
函数声明
//这一系列函数检查item的type是不是某一类型
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
实现原理
取出cJSON节点,判断type是不是指定的type即可
创建
函数声明
//这一系列函数用于创建指定类型的cJSON item
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
//创建,引用到其他的元素,JSON删除时,不会释放。
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
创建数组
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count);
具体分析
创建某一个类的节点过程大致类似。下面具体分析字符串类型的节点过程
//创建字符串的节点
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
{
cJSON *item = cJSON_New_Item(&global_hooks); //1. 分配空间
if(item)
{
item->type = cJSON_String; //2. 设置类型
//3. 设置节点的值。这里要拷贝这个字符串
item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
if(!item->valuestring)
{
cJSON_Delete(item);
return NULL;
}
}
//4. 创建成功,返回
return item;
}
根据传入的数组,创建JSON数组节点,以int类型为例分析:
//创建int类型的数组
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
{
size_t i = 0;
cJSON *n = NULL;
cJSON *p = NULL;
cJSON *a = NULL;
if ((count < 0) || (numbers == NULL))
{
return NULL;
}
a = cJSON_CreateArray(); //1. 创建数组
//所有的元素创建的item, 构成双向链表
for(i = 0; a && (i < (size_t)count); i++) //2. 遍历传入的数字
{
n = cJSON_CreateNumber(numbers[i]); //2.1 创建对象
if (!n)
{
cJSON_Delete(a);
return NULL;
}
if(!i) //2.2 链接到数组上
{
a->child = n;
}
else
{
suffix_object(p, n); //2.2 把n放在p的后面, p->n
}
p = n;
}
//3. 成功,返回创建的数组
return a;
}
添加
函数接口
//添加元素到array
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
添加到数组
/* Add item to array/object. */
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
{
add_item_to_array(array, item);
}
/*把item添加到array*/
static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
{
cJSON *child = NULL;
if ((item == NULL) || (array == NULL))
{
return false;
}
child = array->child; //1. 获取child
if (child == NULL) //2.1 如果为空,说明数组没有元素,这个第一个元素,直接添加
{
/* list is empty, start new one */
array->child = item;
}
else
{
//2.2.1 遍历到最后一个节点
while (child->next)
{
child = child->next;
}
//2.2.2 添加到最后
suffix_object(child, item);
}
return true;
}
添加到对象
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
{
add_item_to_object(object, string, item, &global_hooks, false);
}
/*
object:添加到的对象
string:添加的item的名字
item:添加的item
constant_key:是否为constant key
*/
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) //1.1 是否为constant key,如果是,type中要设置cJSON_StringIsConst
{
new_key = (char*)cast_away_const(string); //constant_key, 不用strdup
new_type = item->type | cJSON_StringIsConst;
}
else //1.2 不是constant key,需要拷贝字符串
{
new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
if (new_key == NULL)
{
return false;
}
new_type = item->type & ~cJSON_StringIsConst;
}
//2. 如果不是const,并且已经存在string了,那么需要先释放
if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
{
hooks->deallocate(item->string);
}
//3. 设置string和type
item->string = new_key;
item->type = new_type;
//4. 添加到array
return add_item_to_array(object, item);
}
删除
接口
/*移除一个节点*/
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
具体分析
以移除数组中的元素为例
//移除which位置的节点,
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
{
cJSON_Delete(cJSON_DetachItemFromArray(array, which));
}
/*移除array上的第which个节点*/
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
{
if (which < 0)
{
return NULL;
}
return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
}
/*
获取array中的第index个节点, 如果超出了index会返回NULL
*/
static cJSON* get_array_item(const cJSON *array, size_t index)
{
cJSON *current_child = NULL;
if (array == NULL)
{
return NULL;
}
current_child = array->child;
while ((current_child != NULL) && (index > 0))
{
index--;
current_child = current_child->next;
}
return current_child;
}
/*
把parent的子节点item移除,并返回item
*/
CJSON_PUBLIC(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(int) cJSON_GetArraySize(const cJSON *array);
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
//获取第i个节点的元素
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
/* Get item "string" from object. Case insensitive. */
//根据名字获取节点
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
//根据名字获取节点,忽略大小写
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
//判断是否存在这个节点
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
具体分析
//获取数组的大小
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
{
cJSON *child = NULL;
size_t size = 0;
if (array == NULL)
{
return 0;
}
child = array->child;
//遍历每个元素
while(child != NULL)
{
size++;
child = child->next;
}
/* FIXME: Can overflow here. Cannot be fixed without breaking the API */
return (int)size;
}
/*
获取array中的第index个节点, 如果超出了index会返回NULL
*/
static cJSON* get_array_item(const cJSON *array, size_t index)
{
cJSON *current_child = NULL;
if (array == NULL)
{
return NULL;
}
current_child = array->child;
while ((current_child != NULL) && (index > 0))
{
index--;
current_child = current_child->next;
}
return current_child;
}
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
{
if (index < 0)
{
return NULL;
}
return get_array_item(array, (size_t)index);
}
/*根据名字找到item*/
static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
{
cJSON *current_element = NULL;
if ((object == NULL) || (name == NULL))
{
return NULL;
}
current_element = object->child;
if (case_sensitive)
{
while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
{
current_element = current_element->next;
}
}
else
{
while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
{
current_element = current_element->next;
}
}
if ((current_element == NULL) || (current_element->string == NULL)) {
return NULL;
}
return current_element;
}
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
{
return get_object_item(object, string, false);
}