cJSON常用接口详细总结(附测试代码)

1、前言

        项目中常用Json格式的数据进行数据mqtt传输或者配置文件读取等操作,本文将常用接口做简单测试给大家参考。

2、Json格式

2.1 Json结构体格式

typedef struct cJSON
{
    /* 通过next/prev 可以找到同级节点或者使用 GetArraySize/GetArrayItem/GetObjectItem等接口来查找同级节点*/
    struct cJSON *next;
    struct cJSON *prev;
    /* 子节点指针 */
    struct cJSON *child;

    /* key的类型 */
    int type;

    /* value类型为字符串时存放字符串首地址                */
    char *valuestring;

    // 测试了一下valueint和valuedouble
    // 当置入整数值的时候,比如12 valueint为12,valuedouble为12.0
    // 当置入小数值的时候,比如12.333 valueint为12,valuedouble为12.333
    /* value类型为数值时存放该数值 */
    int valueint;
    
    /* value类型为数值时存放该数值            */
    double valuedouble;

    /* key的名称 */
    char *string;
} cJSON;

2.2 常用接口

部分常用的接口整理如下:

/**********************创建节点常用接口**********************/
// 创建节点对象
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
// 创建数组节点对象
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
// 创建count个key的相应数据类型的节点对象
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);

/**********************填充节点常用接口**********************/
// 向object节点对象中添加键值对 其中key为name value为number
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object,const char * const name,const double number);
// 向object节点对象中添加键值对 其中key为name value为string
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object,const char * const string);
// 向object节点对象中添加名称为name的对象节点
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object,const char * const name);
// 向object节点对象中添加名称为name的数组对象节点
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object,const char * const name);
// 向array数组中添加item节点对象
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array,cJSON *item);

/**********************解析节点常用接口**********************/
// 从object节点对象中查找key为string的节点作为返回值返回
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object,const char * const string);
// 获取数组中元素个数
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
// 根据index索引返回数组中节点对象
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array,int index);

/***********************转换常用接口*************************/
// 将item整个序列打印出来 格式清晰有换行
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
// 将item整个序列打印出来 只有一整行 无回车等
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
// 将json格式的字符串转为节点对象
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);

/***********************内存释放接口*************************/
// 释放object节点内存 包含其子节点
CJSON_PUBLIC(void) cJSON_free(void *object);

3、测试用例

3.1 简单数据组织

创建两个节点对象,分别向两个节点对象中添加数字和字符串键值对,然后进行格式化输出,代码如下:

#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"

int main()
{
    cJSON *root    = NULL;
    cJSON *bodymsg    = NULL;
    char  *pString = NULL;

    // 创建根节点
    root = cJSON_CreateObject();
    // 创建body节点
    bodymsg = cJSON_CreateObject();

    // 向bodymsg中添加键值对
    cJSON_AddNumberToObject(bodymsg,"BdTestNum",(double)12);
    cJSON_AddItemToObject(bodymsg,"BdTestStr",cJSON_CreateString("bodystring"));

    // 向root中添加键值对
    cJSON_AddNumberToObject(root,"NumTest",(double)1.23);
    cJSON_AddItemToObject(root,"StringTest",cJSON_CreateString("hello"));
    cJSON_AddItemToObject(root,"body",bodymsg);

    // 将root节点进行格式化输出并打印出来
    pString  = cJSON_Print(root); 
    printf("%s\n",pString);

    // 内存释放
    cJSON_Delete(root);
    free(pString);

    return 0;
}

测试输出结果:

 3.2 数组数据组织

数组的组织相对复杂一点,测试代码如下:

#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"

int main()
{
    cJSON *root     = NULL;
    cJSON *arrymsg  = NULL;
    cJSON *arry1    = NULL;
    cJSON *arry2    = NULL;
    char  *pString  = NULL;
    cJSON *arrystr  = NULL;
    char  *pstr[4]  = {"rng","we","edg","ig"};
    
    // 创建根节点
    root = cJSON_CreateObject();

    // 创建arrymsg数组节点
    arrymsg = cJSON_CreateArray();

    // 创建数组内容节点
    arry1 = cJSON_CreateObject();
    arry2 = cJSON_CreateObject();

    // 创建元素全为字符串的数组
    arrystr = cJSON_CreateStringArray(pstr,4);

    // 添加键值对
    cJSON_AddNumberToObject(arry1,"arr1",(double)12);
    cJSON_AddItemToObject(arry2,"arr2",cJSON_CreateString("bodystring"));

    // 向数组添加元素
    cJSON_AddItemToArray(arrymsg,arry1);
    cJSON_AddItemToArray(arrymsg,arry2);
    
    // 向root中添加键值对
    cJSON_AddNumberToObject(root,arrymsg);
    cJSON_AddItemToObject(root,"strbody",arrystr);

    // 将root节点进行格式化输出并打印出来
    pString  = cJSON_Print(root); 
    printf("%s\n",pString);

    // 内存释放
    cJSON_Delete(root);
    free(pString);

    return 0;
}

测试输出结果:

 3.3 获取数据解析

读取json格式数据,进行数据解析和获取,读取文件内容如下:

 测试代码:

#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"

int main()
{
    char configfile[1024] = {0};
    FILE *pFile = fopen("test.json","r");  
    int ret,iRet;
    if (pFile == NULL) 
    { 
        return -1;
    }
    else 
    {
        ret = fread(configfile,1,sizeof(configfile),pFile);
        fclose(pFile);
    
        if (ret > 0) 
        {
            cJSON * root = NULL;

            // 将字符串json格式化
            root = cJSON_Parse(configfile);
            
            if (root == NULL) 
            {
                return -1;
            }
            else 
            {
                // 解析数据
                char   string[10] = {0};
                int    num = 0;
                cJSON * temp;
                cJSON * tempIn;
                cJSON * tempInIn;
                cJSON * arrData;

                // 获取root下面的数值 先获取该对象节点
                temp = cJSON_GetObjectItem(root,"rootnum");
                printf("Get rootnum = %lf\n",temp->valuedouble);

                // 获取第一个body中字符串的值进行打印 获取嵌套body中数字的值进行打印
                temp = cJSON_GetObjectItem(root,"body");

                // 第一个body是一个数组 并且只有一个元素
                for(int i = 0; i < cJSON_GetArraySize(temp); ++i)
                {
                    // 根据索引获取节点对象
                    tempIn = cJSON_GetArrayItem(temp,i);

                    // 获取body中第一个元素的bodystring对象并打印
                    tempInIn = cJSON_GetObjectItem(tempIn,"bodystring");
                    printf("Get bodystring = %s\n",tempInIn->valuestring);

                    // 获取嵌套body 并打印其中元素的值
                    tempInIn = cJSON_GetObjectItem(tempIn,"body");

                    // 嵌套的body也是一个数组 有三个元素
                    for(int j = 0; j < cJSON_GetArraySize(tempInIn); ++j)
                    {
                        arrData = cJSON_GetArrayItem(tempInIn,j);
                        printf("Get bodyIn No.[%d] = %d\n",j,arrData->valueint);
                    }           
                }
                
                cJSON_Delete(root);
            }
        }
        else
        {
            return -1;
        }
    }

    return 0;
}

测试结果:

相关文章

一.C语言中的static关键字 在C语言中,static可以用来修饰局...
浅谈C/C++中的指针和数组(二) 前面已经讨论了指针...
浅谈C/C++中的指针和数组(一)指针是C/C++...
从两个例子分析C语言的声明 在读《C专家编程》一书的第三章时...
C语言文件操作解析(一)在讨论C语言文件操作之前,先了解一下...
C语言文件操作解析(三) 在前面已经讨论了文件打开操作,下面...