• 欢迎大家分享资料!前往留言板评论即可!

12、RDA8910CSDK二次开发:c语言中最好用的JSON解析库—cJSON

合宙 模组资料网 2年前 (2021-05-15) 607次浏览 0个评论 扫描二维码
文章目录[隐藏]

目录

点击这里查看所有博文

  本系列博客所述资料均来自合宙官方,并不是本人原创(只有博客是自己写的),csdk只是得到了口头的允许公开授权。出于热心,本人将自己的所学笔记整理并推出相对应的使用教程,方面其他人学习。为国内的物联网事业发展尽自己的一份绵薄之力,没有为自己谋取私利的想法。若出现侵权现象,请告知本人,本人会立即停止更新,并删除相应的文章和代码。

  本系列博客基于紫光展锐的RDA8910 LTE Cat 1 bis芯片平台开发。理论上适用于合宙的Air720U、Air724U、广和通L610以及安信可的cat-01模块。

  各个厂家的部分配置文件可能不一样,也许会导致设备出现奇怪的问题,其他的模块我也不确定能不能用,自行测试。但是有一点编译下载和监视流程基本一样,可供参考。

  先不管支不支持,如果你用的模块是是紫光展锐的RDA8910,那都不妨一试,也许会有意外收获(也有可能变砖,慎重!!!)。

  我使用的是Air724UG开发板,如果在其他模块上不能用,那也不要强怼,也许是开发包不兼容吧。这里的代码是没有问题的。例程仅供参考!

一、前言

  JSON(JavaScript Object Notation,JavaScript对象表示法)是一种由道格拉斯·克罗克福特构想和设计、轻量级的数据交换语言,该语言以易于让人阅读的文字为基础,用来传输由属性值或者序列性的值组成的数据对象。尽管JSON是JavaScript的一个子集,但JSON是独立于语言的文本格式,并且采用了类似于C语言家族的一些习惯。

  JSON 数据格式与语言无关,脱胎自JavaScript,但当前很多编程语言都支持 JSON 格式数据的生成和解析。JSON 的官方 MIME 类型是 application/json,文件扩展名是 .json。

  JSON 解析器和 JSON 库支持许多不同的编程语言。 JSON 文本格式在语法上与创建 JavaScript 对象的代码相同。 由于这种相似性, 无需解析器, JavaScript 程序能够使用内建的 eval() 函数, 用 JSON 数据来生成原生的 JavaScript 对象。

  JSON 是存储和交换文本信息的语法。 类似 XML。 JSON 比 XML 更小、 更快, 更易解析。

  JSON 具有自我描述性, 语法简洁, 易于理解。

  关于JSON的介绍,需要了解的兄弟们请参考我的合宙Air模块Luat开发专题,第10篇文章JSON字符串的生成与解析

在这里插入图片描述
  总之就是一句话。JSON很常见,虽然与 JavaScript 紧密相连,但 JSON 与语言无关,JSON 使用与其他语言类似的约定(例如,C,C ++,Java,Perl ,Lua和 Python),使 JSON 成为理想的数据交换语言。

  在c语言中同样有很多用于JSON生成和解析的库,其中免费开源好用的当属cJSON。那么今天我们就来耍一下。

  cJSON库文件在demo里面的cJSON例程有提供,直接拷贝一份出来即可使用。不需要做其他的改动。

二、编写测试程序

2.1、了解本例程所用到的函数

  使用cJSON服务需要包含#include "cJSON.h""头文件,我们这里只用到了13个函数,分别是:

/**JSON解析
提供一个JSON块,这将返回一个您可以查询的cJSON对象。
*@param value:JSON字符串
*@return cJSON对象指针
**/

  • CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)

/***从JSON对象中获取键值对。不区分大小写。
*@param object:要查询的cJSON对象
    string:要查询的键值对
*@return cJSON对象指针
**/

  • CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)

/*判断该对象是不是字符串类型
*@param object:要查询的cJSON对象
*@return 真值,是字符串类型
**/

  • CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);

/*判断该对象是不是数字类型
*@param object:要查询的cJSON对象
*@return 真值,是字数字类型
**/

  • CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)

/*获取数组(或对象)中的项目数。
*@param object:要查询的cJSON对象
*@return 项目数
**/

  • CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)

/*删除cJSON结构。
*@param object:要删除的cJSON对象
**/

  • CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)

/*创建一个cJSON对象
*@return 创建的对象
**/
* CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)

/*添加一个字符串到cJSON对象中
*@param object:要添加的cJSON对象
*@param name:要添加的键
*@param string:要添加的值
*@return cJSON对象指针
**/

  • CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);

/*添加一个数字到cJSON对象中
*@param object:要添加的cJSON对象
*@param name:要添加的键
*@param number:要添加的值
*@return cJSON对象指针
**/

  • CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)

/*添加一个cJSON对象到cJSON对象中
*@param object:要添加的cJSON对象
*@param name:要添加的键
*@param item:要添加的值
*@return cJSON对象指针
**/

  • CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);

/*创建一个数组对象
*@param numbers:要创建的数组
*@param count:数组的长度
*@return 创建的对象
**/

  • CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)

/*将cJSON项目/实体/结构呈现为文本。
*@param item:cJSON对象
*@return 字符串
**/

  • CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)

/*释放内存
*@param object:要释放的内存块
**/

  • CJSON_PUBLIC(void) cJSON_free(void *object);

2.2、编写cJSON解析程序

  解析程序负责将一个json格式的字符串转换成cJSON对象,并在其中查找需要的键值对。要注意的是,查找完毕后需要删除cJSON_Parse函数创建的父节点。

    // jsonRoot 是您要剖析的数据
    //首先整体判断是否为一个json格式的数据
    iot_debug_print("[cJSON_Test] cJSON_Parsing Start");
    cJSON *pJsonRoot = cJSON_Parse(jsonRoot);
    //如果是否json格式数据
    if (pJsonRoot != NULL)
    {
        iot_debug_print("[cJSON_Test] cJSON TRUE");
        iot_debug_print("[cJSON_Test] cJSON:%s", jsonRoot);
    }
    else
    {
        iot_debug_print("[cJSON_Test] cJSON ERROR");
    }

    //解析imei字段字符串内容
    cJSON *pimeiAdress = cJSON_GetObjectItem(pJsonRoot, "imei");
    //判断imei字段是否json格式
    if (pimeiAdress)
    {
        //判断mac字段是否string类型
        if (cJSON_IsString(pimeiAdress))
            iot_debug_print("[cJSON_Test] get imeiAdress:%s", pimeiAdress->valuestring);
    }
    else
        iot_debug_print("[cJSON_Test] get imeiAdress failed");

    //解析Num字段int内容
    cJSON *pNumber = cJSON_GetObjectItem(pJsonRoot, "Num");
    //判断Num字段是否存在
    if (pNumber)
    {
        //判断mac字段是否数字整型类型
        if (cJSON_IsNumber(pNumber))
            iot_debug_print("[cJSON_Test] get Num:%d", pNumber->valueint);
    }
    else
        iot_debug_print("[cJSON_Test] get Num failed");

    //解析value字段内容,判断是否为json
    cJSON *pValue = cJSON_GetObjectItem(pJsonRoot, "Value");
    if (pValue)
    {
        //进一步剖析里面的name字段:注意这个根节点是 pValue
        cJSON *pName = cJSON_GetObjectItem(pValue, "name");
        if (pName)
        {
            if (cJSON_IsString(pName))
                iot_debug_print("[cJSON_Test] get value->Name:%s", pName->valuestring);
        }
        else
            iot_debug_print("[cJSON_Test] get pValue->pName failed");

        //进一步剖析里面的age字段:注意这个根节点是 pValue
        cJSON *pAge = cJSON_GetObjectItem(pValue, "age");
        if (pAge)
        {
            if (cJSON_IsNumber(pAge))
                iot_debug_print("[cJSON_Test] get value->Age:%d", pAge->valueint);
        }
        else
            iot_debug_print("[cJSON_Test] get pValue->pAge failed");

        //进一步剖析里面的blog字段:注意这个根节点是 pValue
        cJSON *pBlog = cJSON_GetObjectItem(pValue, "blog");
        if (pBlog)
        {
            if (cJSON_IsString(pBlog))
                iot_debug_print("[cJSON_Test] get value->pBlog:%s", pBlog->valuestring);
        }
        else
            iot_debug_print("[cJSON_Test] get pValue->pBlog failed");
    }
    else
        iot_debug_print("[cJSON_Test] get pValue failed");

    //剖析数组
    cJSON *pArry = cJSON_GetObjectItem(pJsonRoot, "hexArry");
    if (pArry)
    {
        //获取数组长度
        int arryLength = cJSON_GetArraySize(pArry);
        iot_debug_print("[cJSON_Test] get arryLength:%d", arryLength);
        //逐个打印
        int i;
        for (i = 0; i < arryLength; i++)
            iot_debug_print("[cJSON_Test] get cJSON_GetArrayItem(pArry, %d)= %d", i, cJSON_GetArrayItem(pArry, i)->valueint);
    }
    else
        iot_debug_print("[cJSON_Test] get pArry failed");

    //释放内存
    cJSON_Delete(pJsonRoot);

    iot_debug_print("[cJSON_Test] cJSON_Parsing Stop");

  相比Luat中的json解析,cJSON用起来真的是太复杂了。

2.3、编写cJSON生成程序

  生成程序,首先创建一个空的对象(实际是一个链表),然后将不同的键值对依次插入。全部插入完成后,打印查看,最后删除cJSON_CreateObject函数创建的父对象pRoot

    //取一下本地的station的mac地址,保存在全局变量tempMessage
    iot_debug_print("[cJSON_Test] cJSON_Generate Start");
    cJSON *pRoot = cJSON_CreateObject();

    //新增一个字段imei到根点,数值是tempMessage
    char tempMessage[] = "8661111111111111";
    cJSON_AddStringToObject(pRoot, "imei", tempMessage);

    //新增一个字段number到根点,数值是2
    cJSON_AddNumberToObject(pRoot, "number", 2020);

    cJSON *pValue = cJSON_CreateObject();
    cJSON_AddStringToObject(pValue, "name", "cx");
    cJSON_AddNumberToObject(pValue, "age", 17);
    cJSON_AddItemToObject(pRoot, "value", pValue);

    //数组初始化
    int hex[5] = {11, 12, 13, 14, 15};
    cJSON *pHex = cJSON_CreateIntArray(hex, 5); //创建一个长度为5的int型的数组json元素
    cJSON_AddItemToObject(pRoot, "hex", pHex);  //将数组元素添加进pRoot

    char *s = cJSON_Print(pRoot);
    iot_debug_print("[cJSON_Test] creatJson:%s", s);
    //释放内存
    cJSON_free((void *)s);

    //释放内存
    //cJSON_Delete(pHex);
    //释放内存
    //cJSON_Delete(pValue);
    //释放内存
    cJSON_Delete(pRoot);
    iot_debug_print("[cJSON_Test] cJSON_Generate Stop");

三、编译并下载程序

  完整代码在这,自取。

/*
 * @Author: your name
 * @Date: 2020-05-19 14:05:32
 * @LastEditTime: 2020-06-15 00:10:00
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \RDA8910_CSDK\USER\user_main.c
 */

#include "string.h"
//#include "cs_types.h"

#include "osi_log.h"
#include "osi_api.h"

#include "am_openat.h"
#include "am_openat_vat.h"
#include "am_openat_common.h"

#include "iot_debug.h"
#include "iot_uart.h"
#include "iot_os.h"
#include "iot_gpio.h"
#include "iot_pmd.h"
#include "iot_adc.h"
#include "iot_vat.h"
#include "iot_network.h"
#include "iot_socket.h"

#include "cJSON.h"
//#include "MQTTClient.h"

HANDLE TestTask_HANDLE = NULL;

#define jsonRoot "{\r\n"                                                                             \
                 "\"imei\": \"8661111111111111\",\r\n"                                               \
                 "\"Num\": 142,\r\n"                                                                 \
                 "\"Value\": {\r\n"                                                                  \
                 "\"name\": \"cx\",\r\n"                                                             \
                 "\"age\": 18,\r\n"                                                                  \
                 "\"blog\": \"https://blog.csdn.net/weixin_44570083/article/details/104285283\"\r\n" \
                 "},\r\n"                                                                            \
                 "\"hexArry\": [31, 56, 36, 1365, 263]\r\n"                                          \
                 "}\r\n"

//JSON解析
void cJSON_Parsing()
{
    // jsonRoot 是您要剖析的数据
    //首先整体判断是否为一个json格式的数据
    iot_debug_print("[cJSON_Test] cJSON_Parsing Start");
    cJSON *pJsonRoot = cJSON_Parse(jsonRoot);
    //如果是否json格式数据
    if (pJsonRoot != NULL)
    {
        iot_debug_print("[cJSON_Test] cJSON TRUE");
        iot_debug_print("[cJSON_Test] cJSON:%s", jsonRoot);
    }
    else
    {
        iot_debug_print("[cJSON_Test] cJSON ERROR");
    }

    //解析imei字段字符串内容
    cJSON *pimeiAdress = cJSON_GetObjectItem(pJsonRoot, "imei");
    //判断imei字段是否json格式
    if (pimeiAdress)
    {
        //判断mac字段是否string类型
        if (cJSON_IsString(pimeiAdress))
            iot_debug_print("[cJSON_Test] get imeiAdress:%s", pimeiAdress->valuestring);
    }
    else
        iot_debug_print("[cJSON_Test] get imeiAdress failed");

    //解析Num字段int内容
    cJSON *pNumber = cJSON_GetObjectItem(pJsonRoot, "Num");
    //判断Num字段是否存在
    if (pNumber)
    {
        //判断mac字段是否数字整型类型
        if (cJSON_IsNumber(pNumber))
            iot_debug_print("[cJSON_Test] get Num:%d", pNumber->valueint);
    }
    else
        iot_debug_print("[cJSON_Test] get Num failed");

    //解析value字段内容,判断是否为json
    cJSON *pValue = cJSON_GetObjectItem(pJsonRoot, "Value");
    if (pValue)
    {
        //进一步剖析里面的name字段:注意这个根节点是 pValue
        cJSON *pName = cJSON_GetObjectItem(pValue, "name");
        if (pName)
        {
            if (cJSON_IsString(pName))
                iot_debug_print("[cJSON_Test] get value->Name:%s", pName->valuestring);
        }
        else
            iot_debug_print("[cJSON_Test] get pValue->pName failed");

        //进一步剖析里面的age字段:注意这个根节点是 pValue
        cJSON *pAge = cJSON_GetObjectItem(pValue, "age");
        if (pAge)
        {
            if (cJSON_IsNumber(pAge))
                iot_debug_print("[cJSON_Test] get value->Age:%d", pAge->valueint);
        }
        else
            iot_debug_print("[cJSON_Test] get pValue->pAge failed");

        //进一步剖析里面的blog字段:注意这个根节点是 pValue
        cJSON *pBlog = cJSON_GetObjectItem(pValue, "blog");
        if (pBlog)
        {
            if (cJSON_IsString(pBlog))
                iot_debug_print("[cJSON_Test] get value->pBlog:%s", pBlog->valuestring);
        }
        else
            iot_debug_print("[cJSON_Test] get pValue->pBlog failed");
    }
    else
        iot_debug_print("[cJSON_Test] get pValue failed");

    //剖析数组
    cJSON *pArry = cJSON_GetObjectItem(pJsonRoot, "hexArry");
    if (pArry)
    {
        //获取数组长度
        int arryLength = cJSON_GetArraySize(pArry);
        iot_debug_print("[cJSON_Test] get arryLength:%d", arryLength);
        //逐个打印
        int i;
        for (i = 0; i < arryLength; i++)
            iot_debug_print("[cJSON_Test] get cJSON_GetArrayItem(pArry, %d)= %d", i, cJSON_GetArrayItem(pArry, i)->valueint);
    }
    else
        iot_debug_print("[cJSON_Test] get pArry failed");

    //释放内存
    cJSON_Delete(pJsonRoot);

    iot_debug_print("[cJSON_Test] cJSON_Parsing Stop");
}

//JSON生成
void cJSON_Generate()
{
    //取一下本地的station的mac地址,保存在全局变量tempMessage
    iot_debug_print("[cJSON_Test] cJSON_Generate Start");
    cJSON *pRoot = cJSON_CreateObject();

    //新增一个字段imei到根点,数值是tempMessage
    char tempMessage[] = "8661111111111111";
    cJSON_AddStringToObject(pRoot, "imei", tempMessage);

    //新增一个字段number到根点,数值是2
    cJSON_AddNumberToObject(pRoot, "number", 2020);

    cJSON *pValue = cJSON_CreateObject();
    cJSON_AddStringToObject(pValue, "name", "cx");
    cJSON_AddNumberToObject(pValue, "age", 17);
    cJSON_AddItemToObject(pRoot, "value", pValue);

    //数组初始化
    int hex[5] = {11, 12, 13, 14, 15};
    cJSON *pHex = cJSON_CreateIntArray(hex, 5); //创建一个长度为5的int型的数组json元素
    cJSON_AddItemToObject(pRoot, "hex", pHex);  //将数组元素添加进pRoot

    char *s = cJSON_Print(pRoot);
    iot_debug_print("[cJSON_Test] creatJson:%s", s);
    //释放内存
    cJSON_free((void *)s);

    //释放内存
    //cJSON_Delete(pHex);
    //释放内存
    //cJSON_Delete(pValue);
    //释放内存
    cJSON_Delete(pRoot);
    iot_debug_print("[cJSON_Test] cJSON_Generate Stop");
}

//main函数
int appimg_enter(void *param)
{
    //系统休眠
    iot_os_sleep(20000);
    cJSON_Parsing();
    cJSON_Generate();
    return 0;
}

//退出提示
void appimg_exit(void)
{
    OSI_LOGI(0, "application image exit");
}

四、分析结果

  查看输出的日志信息,可以看到JSON的解析与生成都是正确的。

[00:11:49.559]  [59599] [ 7216] [                ] [      ] [ ] OPEN/  : [cJSON_Test] cJSON_Parsing Start
[00:11:49.559]  [59603] [ 7217] [                ] [      ] [ ] OPEN/  : [cJSON_Test] cJSON TRUE
[00:11:49.559]  [59604] [ 7218] [                ] [      ] [ ] OPEN/  : [cJSON_Test] cJSON:{
"imei": "8661111111111111",
"Num": 142,
"Value": {
"name": "cx",
"age": 18,
"blog": "https://blog.csdn.net/weixin_44570083/article/details/104285283"
},
"hexArry": [31, 56, 36, 1365, 263]
}
[00:11:49.559]  [59605] [ 7219] [                ] [      ] [ ] OPEN/  : [cJSON_Test] get imeiAdress:8661111111111111
[00:11:49.559]  [59606] [ 7220] [                ] [      ] [ ] OPEN/  : [cJSON_Test] get Num:142
[00:11:49.559]  [59606] [ 7221] [                ] [      ] [ ] OPEN/  : [cJSON_Test] get value->Name:cx
[00:11:49.559]  [59606] [ 7222] [                ] [      ] [ ] OPEN/  : [cJSON_Test] get value->Age:18
[00:11:49.559]  [59607] [ 7223] [                ] [      ] [ ] OPEN/  : [cJSON_Test] get value->pBlog:https://blog.csdn.net/weixin_44570083/article/details/104285283
[00:11:49.559]  [59607] [ 7224] [                ] [      ] [ ] OPEN/  : [cJSON_Test] get arryLength:5
[00:11:49.559]  [59608] [ 7225] [                ] [      ] [ ] OPEN/  : [cJSON_Test] get cJSON_GetArrayItem(pArry, 0)= 31
[00:11:49.559]  [59608] [ 7226] [                ] [      ] [ ] OPEN/  : [cJSON_Test] get cJSON_GetArrayItem(pArry, 1)= 56
[00:11:49.559]  [59608] [ 7227] [                ] [      ] [ ] OPEN/  : [cJSON_Test] get cJSON_GetArrayItem(pArry, 2)= 36
[00:11:49.559]  [59608] [ 7228] [                ] [      ] [ ] OPEN/  : [cJSON_Test] get cJSON_GetArrayItem(pArry, 3)= 1365
[00:11:49.559]  [59609] [ 7229] [                ] [      ] [ ] OPEN/  : [cJSON_Test] get cJSON_GetArrayItem(pArry, 4)= 263
[00:11:49.559]  [59609] [ 7230] [                ] [      ] [ ] OPEN/  : [cJSON_Test] cJSON_Parsing Stop
[00:11:49.559]  [59610] [ 7231] [                ] [      ] [ ] OPEN/  : [cJSON_Test] cJSON_Generate Start
[00:11:49.559]  [59619] [ 7232] [                ] [      ] [ ] OPEN/  : [cJSON_Test] creatJson:{
    "imei": "8661111111111111",
    "number":   2020,
    "value":    {
        "name": "cx",
        "age":  17
    },
    "hex":  [11, 12, 13, 14, 15]
}
[00:11:49.615]  [59620] [ 7233] [                ] [      ] [ ] OPEN/  : [cJSON_Test] cJSON_Generate Stop

不会下载的点击这里,进去查看我的RDA8910 CSDK二次开发入门教程专题第一篇博文1、RDA8910CSDK二次开发:环境搭建里面讲了怎么下载
这里只是我的学习笔记,拿出来给大家分享,欢迎大家批评指正,本篇教程到此结束


喜欢 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址