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

目录

点击这里查看所有博文

  本系列博客所述资料均来自合宙官方,并不是本人原创(只有博客是自己写的),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对象指针
*
/

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

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

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

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

/创建一个cJSON对象
*@return 创建的对象
*
/

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

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

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//取一下本地的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");

三、编译并下载程序

  完整代码在这,自取。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/*
* @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的解析与生成都是正确的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[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二次开发:环境搭建里面讲了怎么下载
这里只是我的学习笔记,拿出来给大家分享,欢迎大家批评指正,本篇教程到此结束

上次更新 2021-01-28