• cJSON的使用


    1 安装cJSON

    github地址:https://github.com/DaveGamble/cJSON.git

    1. 下载完成后进入cJSON目录,执行下面命令生成Makefile文件

      mkdir build
      cd build
      cmake ..
      
    2. 执行下面命令安装cJSON库

      make install
      
      • 默认将头文件安装到/usr/local/include/cjson路径下
      • 默认将链接库安装到/usr/local/lib路径下
    3. 一些CMake选项介绍

      选项 功能 默认值
      -DENABLE_CJSON_TEST 开启编译tests On
      -DENABLE_CJSON_UTILS 开启编译cJSON_Utils Off
      -DENABLE_TARGET_EXPORT 开启CMake目标导出 On
      -DENABLE_CUSTOM_COMPILER_FLAGS 开启自定义编译选项 On
      -DENABLE_VALGRIND 使用valgrind运行tests Off
      -DENABLE_SANITIZERS 使用AddressSanitizer和UndefinedBehaviorSanitizer编译cJSON Off
      -DENABLE_SAFE_STACK 开启SafeStack工具检测(目前只能在Clang编译器上工作) Off
      -DBUILD_SHARED_LIBS 编译动态库 On
      -DBUILD_SHARED_AND_STATIC_LIBS 编译动态库和静态库 Off
      -DCMAKE_INSTALL_PREFIX 设置安装路径前缀
      -DENABLE_LOCALES 开启使用localeconv方法 On
      -DCJSON_OVERRIDE_BUILD_SHARED_LIBS 使用-DCJSON_BUILD_SHARED_LIBS覆盖BUILD_SHARED_LIBS的值
    4. 在代码中引入头文件

      #include <cjson/cJSON.h>
      

    2 cJSON数据结构

    • cJSON使用cJSON结构体表示JSON数据

      typedef struct cJSON
      {
          /* next和prev允许你遍历array/object链,或者使用GetArraySize/GetArrayItem/GetObjectItem方法 */
          struct cJSON *next;
          struct cJSON *prev;
          /* array/object会拥有child指针,指向它包含的一连串元素 */
          struct cJSON *child;
      
          /* 类型 */
          int type;
      
          /* 如果type为cJSON_String或cJSON_Raw,使用它保存string值 */
          char *valuestring;
          /* 将值写入valueint已过时,使用cJSON_SetNumberValue代替 */
          int valueint;
          /* 如果type为cJSON_Number,使用它保存number值 */
          double valuedouble;
          /* 如果该节点是array或者object的子元素,则使用它保存名称字符串 */
          char *string;
      } cJSON;
      
    • type取值

      取值 含义 备注 检查
      cJSON_Invalid 非法 不包含任何值 cJSON_IsInvalid
      cJSON_False false cJSON_IsFalse/cJSON_IsBool
      cJSON_True true cJSON_IsTrue/cJSON_IsBool
      cJSON_NULL null cJSON_IsNull
      cJSON_Number 数字 值将以double类型保存在valuedouble中,同时也保存在valueint中,如果超出整形范围,则valueint值为INT_MAX或者INT_MIN cJSON_IsNumber
      cJSON_String 字符串 ''结尾的形式保存在valuestring cJSON_IsString
      cJSON_Array 数组 child指针指向数组中各个元素,各元素通过next/prev指针串在一起形成链表 cJSON_IsArray
      cJSON_Object 对象 同数组保存形式相同,只不过对象中的各个元素会将它们的key值存储在string cJSON_IsObject
      cJSON_Raw 任意JSON类型 ''结尾的形式保存在valuestring中,使用cJSON解析时不会生成这个类型,并且cJSON不会校验JSON的合法性 cJSON_IsRaw
      cJSON_IsReference 引用 child指向的元素或者valuestring不被当前节点拥有,当使用cJSON_Delete时,只会释放当前节点,而不会释放它的childvaluestring
      cJSON_StringIsConst 常量字符串 string指向一个常量字符串,当使用cJSON_Delete时,将不会释放string

    3 创建cJSON数据

    对于每种type,都有一个与之对应的cJSON_Create...方法用于创建该类型的节点,所有方法都会创建一个cJSON结构体,可以使用cJSON_Delete释放它

    注意:

    • 不能使用cJSON_Delete释放array或object当中的元素,当array或者object被释放时,其中的元素也会自动释放
    • 可以使用cJSON_SetValueString改变cJSON_String节点的valuestring值,而不需要手动释放之前的valuestring

    3.1 基本类型

    类型 创建方法 说明
    null cJSON_CreateNull
    boolean cJSON_CreateTrue/cJSON_CreateFalse/cJSON_CreateBool
    number cJSON_CreateNumber 将同时设置valuedoublevalueint,如果数字的值超过整形范围,则valueint将被设为INT_MAXINT_MIN
    string cJSON_CreateString/cJSON_CreateStringReference cJSON_CreateString会拷贝字符串,而cJSON_CreateStringReference直接指向设置的字符串

    3.2 数组

    3.2.1 创建数组

    • cJSON_CreateArray:创建一个空数组
    • cJSON_CreateArrayReference:创建一个数组,但是它里面的所有元素都不属于它自己,所以不能使用cJSON_Delete删除它里面的内容

    3.2.2 向数组中添加元素

    • cJSON_AddItemToArray:在数组尾端添加元素
    • cJSON_AddItemReferenceToArray:将另一个元素的引用添加进数组
    • cJSON_InsertItemInArray:在指定索引处插入元素

    3.2.3 获取数组中的元素

    • cJSON_GetArrayItem:根据索引获取元素

    • cJSON_DetachItemFromArray:根据索引获取数组中的元素,并将其从数组中分离,以便后续能够继续使用

    3.2.4 删除数组中的元素

    • cJSON_DeleteItemFromArray:根据索引删除数组中的元素

    3.2.5 替换数组中的元素

    • cJSON_ReplaceItemInArray:根据索引替换元素
    • cJSON_ReplaceItemViaPointer:根据指针替换元素,失败返回0

    3.2.6 获取数组的大小

    • cJSON_GetArraySize:获取数组的大小

    3.2.7 迭代数组中的元素

    • cJSON_ArrayForEach:在(O(n))的时间内迭代数组中的元素

    3.3 对象

    3.3.1 创建对象

    • cJSON_CreateObject:创建一个空对象
    • cJSON_CreateObjectReference:创建一个对象,但是它里面的所有元素都不属于它自己,所以不能使用cJSON_Delete删除它里面的内容

    3.3.2 向对象中添加元素

    • cJSON_AddItemToObject:向对象中添加一个元素
    • cJSON_AddItemToObjectCS:向对象中添加一个名称(对象的key,即cJSON结构体中的string)为常量或者引用的元素
    • cJSON_AddItemReferenceToObject:将另一个元素的引用添加进对象

    3.3.3 获取对象中的元素

    • cJSON_GetObjectItemCaseSensitive:获取对象中的元素

    • cJSON_DetachItemFromObjectCaseSensitive:分离并获取对象中的元素

    3.3.4 删除对象中的元素

    • cJSON_DeleteItemFromObjectCaseSensitive:删除对象中的元素

    3.3.5 替换对象中的元素

    • cJSON_ReplaceItemInObjectCaseSensitive:根据key替换对象中的元素
    • cJSON_ReplaceItemViaPointer:根据指针替换对象中的元素,失败返回0

    3.3.6 获取对象的大小

    • cJSON_GetArraySize:获取对象的大小

    3.3.7 迭代对象中的元素

    • cJSON_ArrayForEach:迭代对象中的元素

    3.3.8 快速创建并添加元素到对象

    cJSON提供了快速创建并添加到对象的方法,这些方法返回指向新创建元素的指针,如果失败,则返回NULL

    • cJSON_AddNullToObject
    • cJSON_AddTrueToObject
    • cJSON_AddFalseToObject
    • cJSON_AddBoolToObject
    • cJSON_AddNumberToObject
    • cJSON_AddStringToObject
    • cJSON_AddRawToObject
    • cJSON_AddObjectToObject
    • cJSON_AddArrayToObject

    4 cJSON解析与输出JSON

    4.1 解析JSON

    cJSON提供的解析函数的返回值需要手动调用cJSON_Delete释放

    • cJSON_Parse:解析以''结尾的JSON字符串

      cJSON * cJSON_Parse(const char *value);
      
    • cJSON_ParseWithLength:解析指定长度的JSON字符串(可以不以''结尾)

      cJSON * cJSON_ParseWithLength(const char *value, size_t buffer_length);
      
    • cJSON_ParseWithOpts

      cJSON * cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
      
      • return_parse_end:返回指向输入字符串中JSON的结束位置,或解析出错的位置
      • require_null_terminated:是否禁止输入字符串中的JSON后面还包含有数据
    • cJSON_ParseWithLengthOpts

      cJSON * cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
      

    4.2 输出JSON

    cJSON提供的输出函数的返回值需要手动调用free释放

    • cJSON_Print:输出经过空白字符格式化后的JSON

      char * cJSON_Print(const cJSON *item);
      
    • cJSON_PrintUnformatted:输出没有经过空白字符格式化后的JSON

      char * cJSON_PrintUnformatted(const cJSON *item);
      
    • cJSON_PrintBuffered:输出JSON到指定大小的buffer

      char * cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
      
      • prebuffer:指定输出buffer的初始大小
      • fmt:是否使用空白字符进行格式化
    • cJSON_PrintPreallocated:输出JSON到静态buffer,从而避免动态分配内存,当buffer大小不够时,调用失败,返回0,成功时返回1

      cJSON_bool cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
      

      注意:至少提供5字节大小的buffer

    5 cJSON使用示例

    {
        "name": "Awesome 4K",
        "resolutions": [
            {
                "width": 1280,
                "height": 720
            },
            {
                "width": 1920,
                "height": 1080
            },
            {
                "width": 3840,
                "height": 2160
            }
        ]
    }
    

    5.1 打印输出JSON

    5.1.1 方法1

    //create a monitor with a list of supported resolutions
    //NOTE: Returns a heap allocated string, you are required to free it after use.
    char *create_monitor(void)
    {
        const unsigned int resolution_numbers[3][2] = {
            {1280, 720},
            {1920, 1080},
            {3840, 2160}
        };
        char *string = NULL;
        cJSON *name = NULL;
        cJSON *resolutions = NULL;
        cJSON *resolution = NULL;
        cJSON *width = NULL;
        cJSON *height = NULL;
        size_t index = 0;
    
        cJSON *monitor = cJSON_CreateObject();
        if (monitor == NULL)
        {
            goto end;
        }
    
        name = cJSON_CreateString("Awesome 4K");
        if (name == NULL)
        {
            goto end;
        }
        /* after creation was successful, immediately add it to the monitor,
         * thereby transferring ownership of the pointer to it */
        cJSON_AddItemToObject(monitor, "name", name);
    
        resolutions = cJSON_CreateArray();
        if (resolutions == NULL)
        {
            goto end;
        }
        cJSON_AddItemToObject(monitor, "resolutions", resolutions);
    
        for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index)
        {
            resolution = cJSON_CreateObject();
            if (resolution == NULL)
            {
                goto end;
            }
            cJSON_AddItemToArray(resolutions, resolution);
    
            width = cJSON_CreateNumber(resolution_numbers[index][0]);
            if (width == NULL)
            {
                goto end;
            }
            cJSON_AddItemToObject(resolution, "width", width);
    
            height = cJSON_CreateNumber(resolution_numbers[index][1]);
            if (height == NULL)
            {
                goto end;
            }
            cJSON_AddItemToObject(resolution, "height", height);
        }
    
        string = cJSON_Print(monitor);
        if (string == NULL)
        {
            fprintf(stderr, "Failed to print monitor.
    ");
        }
    
    end:
        cJSON_Delete(monitor);
        return string;
    
    

    5.1.2 方法2

    使用cJSON_Add...ToObject快捷创建和添加元素

    //NOTE: Returns a heap allocated string, you are required to free it after use.
    char *create_monitor_with_helpers(void)
    {
        const unsigned int resolution_numbers[3][2] = {
            {1280, 720},
            {1920, 1080},
            {3840, 2160}
        };
        char *string = NULL;
        cJSON *resolutions = NULL;
        size_t index = 0;
    
        cJSON *monitor = cJSON_CreateObject();
    
        if (cJSON_AddStringToObject(monitor, "name", "Awesome 4K") == NULL)
        {
            goto end;
        }
    
        resolutions = cJSON_AddArrayToObject(monitor, "resolutions");
        if (resolutions == NULL)
        {
            goto end;
        }
    
        for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index)
        {
            cJSON *resolution = cJSON_CreateObject();
    
            if (cJSON_AddNumberToObject(resolution, "width", resolution_numbers[index][0]) == NULL)
            {
                goto end;
            }
    
            if (cJSON_AddNumberToObject(resolution, "height", resolution_numbers[index][1]) == NULL)
            {
                goto end;
            }
    
            cJSON_AddItemToArray(resolutions, resolution);
        }
    
        string = cJSON_Print(monitor);
        if (string == NULL)
        {
            fprintf(stderr, "Failed to print monitor.
    ");
        }
    
    end:
        cJSON_Delete(monitor);
        return string;
    }
    

    5.2 解析JSON

    /* return 1 if the monitor supports full hd, 0 otherwise */
    int supports_full_hd(const char * const monitor)
    {
        const cJSON *resolution = NULL;
        const cJSON *resolutions = NULL;
        const cJSON *name = NULL;
        int status = 0;
        cJSON *monitor_json = cJSON_Parse(monitor);
        if (monitor_json == NULL)
        {
            const char *error_ptr = cJSON_GetErrorPtr();
            if (error_ptr != NULL)
            {
                fprintf(stderr, "Error before: %s
    ", error_ptr);
            }
            status = 0;
            goto end;
        }
    
        name = cJSON_GetObjectItemCaseSensitive(monitor_json, "name");
        if (cJSON_IsString(name) && (name->valuestring != NULL))
        {
            printf("Checking monitor "%s"
    ", name->valuestring);
        }
    
        resolutions = cJSON_GetObjectItemCaseSensitive(monitor_json, "resolutions");
        cJSON_ArrayForEach(resolution, resolutions)
        {
            cJSON *width = cJSON_GetObjectItemCaseSensitive(resolution, "width");
            cJSON *height = cJSON_GetObjectItemCaseSensitive(resolution, "height");
    
            if (!cJSON_IsNumber(width) || !cJSON_IsNumber(height))
            {
                status = 0;
                goto end;
            }
    
            if ((width->valuedouble == 1920) && (height->valuedouble == 1080))
            {
                status = 1;
                goto end;
            }
        }
    
    end:
        cJSON_Delete(monitor_json);
        return status;
    }
    
  • 相关阅读:
    解说asp.net core MVC 过滤器的执行顺序
    asp.net core 2.0 Microsoft.Extensions.Logging 文本文件日志扩展
    【技术累积】【点】【java】【30】代理模式
    【技术累积】【点】【java】【29】MapUtils
    【技术累积】【点】【java】【28】Map遍历
    【技术累积】【点】【java】【27】@JSONField
    【技术累积】【点】【java】【26】@Value默认值
    【技术累积】【点】【java】【25】Orderd
    【技术累积】【点】【java】【23】super以及重写重载
    【技术累积】【线】【java】【2】AOP
  • 原文地址:https://www.cnblogs.com/qinjinyu/p/14086938.html
Copyright © 2020-2023  润新知