目录
1.cJSON源码获取
2.cJSON的使用
2.1 增
2.2 删
2.3 改
2.4 查
3.使用注意事项
4.cJSON源码简要分析
工作差不多一年,有很多次用到cJSON这个开源库,这个库用起来很简单,但是也有些地方需要注意。这里来记录下。
1.cJSON源码获取
cJSON库获取
2.cJSON的使用
将上面所有文件下载下来后,这里只需要关注两个文件:cJSON.c和cJSON.h
下面就来看看这两个文件中的代码如何使用:
2.1 增
相关API:
/* Helper functions for creating and adding items to an object at the same time.
* They return the added item or NULL on failure. */
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
举例:
#include <stdio.h>
#include "cJSON.h"
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
int main(void)
{
char jsonBuf[] = "{\"name\":\"lhsmd\", \"sex\":\"男\", \"fav\":{\"eat\":\"water\"}}";
cJSON *cJSONTest = cJSON_Parse(jsonBuf); /* 记得调用cJSON_Delete释放空间 */
cJSON *p = cJSON_GetObjectItem(cJSONTest, "name");
if(cJSON_IsString(p)) /* 判断key的value是否为string */
{
printf("%s\r\n", p->valuestring); /* 输出 */
}
cJSON *p1 = cJSON_AddStringToObject(cJSONTest, "add", "me");
if(p1 != NULL)
{
char *p2 = cJSON_Print(cJSONTest); /* 按照格式输出json cJSON_PrintUnformatted表示格式化输出输出是一长串 */
if(p2 != NULL)
{
printf("%s\r\n", p2);
free(p2);
p2 = NULL;
}
}
cJSON_Delete(cJSONTest);
return 0;
}
输出结果:
2.2 删
相关API:
/* Remove/Detach items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
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);
举例:
#include <stdio.h>
#include "cJSON.h"
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
int main(void)
{
char jsonBuf[] = "{\"name\":\"lhsmd\", \"sex\":\"男\", \"fav\":{\"eat\":\"water\"}}";
cJSON *cJSONTest = cJSON_Parse(jsonBuf); /* 记得调用cJSON_Delete释放空间 */
cJSON *p = cJSON_GetObjectItem(cJSONTest, "name");
if(cJSON_IsString(p)) /* 判断key的value是否为string */
{
printf("%s\r\n", p->valuestring); /* 输出 */
}
cJSON_DeleteItemFromObject(cJSONTest, "name");
char *p3 = cJSON_Print(cJSONTest); /* 按照格式输出json cJSON_PrintUnformatted表示格式化输出输出是一长串 */
if(p3 != NULL)
{
printf("%s\r\n", p3);
free(p3);
p3 = NULL;
}
cJSON_Delete(cJSONTest);
return 0;
}
输出:
2.3 改
相关API:
/* Update array items. */
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
举例:
#include <stdio.h>
#include "cJSON.h"
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
int main(void)
{
char jsonBuf[] = "{\"name\":\"lh\", \"sex\":\"男\", \"fav\":{\"eat\":\"water\"}}";
cJSON *cJSONTest = cJSON_Parse(jsonBuf); /* 记得调用cJSON_Delete释放空间 */
cJSON *p = cJSON_GetObjectItem(cJSONTest, "name");
if(cJSON_IsString(p)) /* 判断key的value是否为string */
{
printf("%s\r\n", p->valuestring); /* 输出 */
}
cJSON_ReplaceItemInObjectCaseSensitive(cJSONTest, "name", cJSON_CreateString("smd"));
char *p2 = cJSON_Print(cJSONTest); /* 按照格式输出json cJSON_PrintUnformatted表示格式化输出输出是一长串 */
if(p2 != NULL)
{
printf("%s\r\n", p2);
free(p2);
p2 = NULL;
}
cJSON *json = cJSON_CreateObject();
if(json != NULL)
{
if(cJSON_AddStringToObject(json, "eat" ,"food"))
{
if(cJSON_ReplaceItemInObjectCaseSensitive(cJSONTest, "fav", json))
{
p2 = cJSON_Print(cJSONTest); /* 按照格式输出json cJSON_PrintUnformatted表示格式化输出输出是一长串 */
if(p2 != NULL)
{
printf("%s\r\n", p2);
free(p2);
p2 = NULL;
}
}
}
}
cJSON_Delete(cJSONTest);
return 0;
}
输出:
2.4 查
查在使用中是使用最多的了,这里给一个实际用到的例子:
现在有一个WIFI模组,需要获取到了来自云端服务器的数据,这些数据是以json的格式下发的,在WIFI模组本地,开启了一个任务(线程),时刻监控来自云端服务器的数据,接收到数据后,需要在这些json数据中提取你想要的数据。现在你已经知道接收数据的格式以及需要提取value的key,那么简单地你可以这么实现:
(代码暂时找不到了,待后续有时间补上)未完待续~~~~~~~~~~~~~
3.使用注意事项
在使用cJSON的过程,需要注意堆空间的释放,具体需要关注的对象有:
1.cJSON_Print系列,需要使用free或者cJSON_free释放
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. */
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
2.cJSON_Create系列,使用cJSON_Delete释放
/* These calls create a cJSON item of the appropriate type. */
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);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* Create a string where valuestring references a string so
* it will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
/* Create an object/array that only references it's elements so
* they will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
/* These utilities create an Array of count items.
* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
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 *const *strings, int count);
3.cJSON_Parse,使用cJSON_Delete释放
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
4.cJSON源码简要分析
在cJSON源码的cJSON.h中,有一个很重要的结构体:
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
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. */
struct cJSON *child;
/* The type of the item, as above. */
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. */
char *string;
} cJSON;
这是一个双向循环链表,事实上,从代码分析,在给定json的数据中,每一个键值对都是一个链表里面的一个节点。json数据的增删改查都是通过这个双向链表实现的。
如果有时间,在介绍学习具体的源码。
|