cJSON最小指南

介绍

cJSON是一个开源的、精简的、可移植的json解析库,使用C语言编写而成,比较受嵌入式开发者的青睐

数据结构

平行节点看:cJSON是一个双向链表的数据结构,next和prev分别指向当前节点的下一个节点和上一个节点,不存在的节点为NULL

父子节点看:cJSON是一个树目录的数据结构,child指向子节点

/* 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;

文件读取

const char *file = "demo.json";
FILE* fp = fopen(file, "rb");
char* data = NULL;
if (fp != NULL)
{
	fseek(fp, 0, SEEK_SET);
	long begin = ftell(fp);
	fseek(fp, 0, SEEK_END);
	long end = ftell(fp);
	long file_size = end - begin;
	fseek(fp, 0, SEEK_SET);
	char* data = (char*)malloc(file_size);
	while (fread(data, 1, file_size, fp) == 1);
}

对象解析

cJSON* root = cJSON_Parse(data);
if(!root)
{
    printf("invalid json object\n");
}

对象打印

printf("%s\n", cJSON_Print(root));

字段解析

子对象

cJSON* channels = cJSON_GetObjectItem(root, "module");

数组对象

#define COUNT 10
int channel_array[COUNT];
if (cJSON_IsArray(channels))
{
	printf("channels :\n%s\n\n", cJSON_Print(channels));
    int channelSize = cJSON_GetArraySize(channels);
    if (COUNT == channelSize) 
    {
        for (int i = 0; i < channelSize; i++)
        {
            channel_array[i] = cJSON_GetArrayItem(channels, i)->valueint;
        }
    }
}

整型数值

cJSON* filter = cJSON_GetObjectItem(root, "filter");
printf("filter : %d\n", filter->valueint);

浮点型数值

cJSON* temperature = cJSON_GetObjectItem(root, "temperature");
printf("temperature : %d\n", filter->valuedouble);

对象构造

构造节点

cJSON* system_node = cJSON_CreateObject();
cJSON* json = cJSON_CreateObject();

添加成员

下面示例展示如何添加数值型成员、数组型成员、字符串型成员到json对象

int temp = 0;
int humi = 0;
SHT4xA_get_rht(0xFD, &temp, &humi);
cJSON_AddNumberToObject(system_node, "temperature", temp / 1000.0);			// 添加数值型成员
cJSON_AddNumberToObject(system_node, "humidity",    humi / 1000.0);			// 添加数值型成员
cJSON_AddItemToObject(json, "environment", system_node);					// 添加节点型成员
cJSON* voltage_max = cJSON_CreateArray();
{
    int voltage;
    int ret;
    for(int pd = 0; pd < 5; pd++) 
    {
        cJSON_AddItemToArray(voltage_max, cJSON_CreateNumber(100));			// 添加数值型成员到数组
    }
    cJSON_AddItemToObject(json, "voltage_max", voltage_max);				// 添加数组到json对象
}
cJSON_AddStringToObject(json, "alarm_code", "voltage too high");			// 添加字符串型成员到json对象

资源回收

根节点对象需要删除,文件buffer需要释放,文件句柄需要关闭

if (root)
{
    cJSON_Delete(root);		// 根节点会遍历所有子节点,释放内存
    free(data);				// 是否文件buffer
    fclose(fp);				// 关闭文件句柄
}

注意事项

Windows平台换行符为CR LF,而Unix平台换行符为LF,在Windows平台用cJSON库解析json文件会出现识别不了的问题,需要将json文件转成Unix换行符才能正确识别

接口

序号 原型 用法
1 cJSON_bool cJSON_IsBool(const cJSON * const item) 判断item是否Bool类型
2 cJSON_bool cJSON_IsNull(const cJSON * const item) 判断item是否空指针
3 cJSON_bool cJSON_IsNumber(const cJSON * const item) 判断item是否数值类型
4 cJSON_bool cJSON_IsString(const cJSON * const item) 判断item是否字符串
5 cJSON_bool cJSON_IsArray(const cJSON * const item) 判断item是否数组
6 cJSON_bool cJSON_IsObject(const cJSON * const item) 判断item是否json对象
7 cJSON* cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean) 添加布尔型成员到object对象
8 cJSON* cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number) 添加数值成员到object对象
9 cJSON* cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string) 添加字符串成员到object对象
10 cJSON* cJSON_AddObjectToObject(cJSON * const object, const char * const name) 添加空json成员到object对象

版本号

打印cJSON版本号

printf("Json Version : %d.%d.%d\n", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
阅读剩余
THE END