cJSON讲解,及ESP32使用ESP-IDF的cJSON组件库案例
提醒:文章最后说明讲解ESP IDF组件库的cJSON库调用
一、cJSON基础
json轻量级的数据交换格式
json语法规则:
- 数据在名称/值对中。
- 数据由逗号分隔。
- 大括号{ }保存对象。
- 中括号[ ]保存数组,数组可以包含多个对象。
cJSON使用cJSON结构数据类型表示JSON数据,数据类型如下
/* The cJSON structure: */
typedef struct cJSON
{
struct cJSON *next;
struct cJSON *prev;
struct cJSON *child;
int type;
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
double valuedouble;
char *string;
} cJSON;
1.cJOSN结构体为一个双向列表,并可通过child指针访问下一层。
2.type变量决定数据项类型(值的类型),数据项可以是字符串可以是整形,也可以是浮点型。如果是整形值的话可从valueint,如果是浮点型的话可从valuedouble取出,以此类推。
3.string可理解为节点的名称,即为键
二、cJSON数据封装
封装JSON数据的过程,其实就是创建链表和向链表中添加节点的过程。
首先来讲述一下链表中的一些术语:
- 头指针:指向链表头结点的指针;
- 头结点:不存放有效数据,方便链表操作;
- 首节点:第一个存放有效数据的节点;
- 尾节点:最后一个存放有效数据的节点;
明白了这几个概念之后,我们开始讲述创建一段完整的JSON数据,即如何创建一条完整的链表。
cJSON重要函数说明
- 创建链表头指针
(cJSON* ) cjson_pointer = NULL;
- 创建一个JSON数据对象
(cJSON *) cJSON_CreateObject(void);
- 创建一个JSON数组对象
(cJSON *) cJSON_CreateArray(void);
- 添加一条字符串类型的JSON数据(添加一个链表节点)
cJSON* cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
- 添加一条整数类型的JSON数据(添加一个链表节点)
cJSON* cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
- JSON嵌套
向对象中添加
cJSON_bool cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
向数组中添加
void cJSON_AddItemToArray(cJSON *array, cJSON *item);
- 解析整段JSON数据,并将链表头结点地址返回,赋值给头指针
(cJSON *) cJSON_Parse(const char *value);
- 根据键值对的名称从链表中取出对应的值,返回该键值对(链表节点)的地址
(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
- 如果JSON数据的值是数组,使用下面的两个API提取数据
(int) cJSON_GetArraySize(const cJSON *array);
(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
- cJSON_Delete() 会删除一个节点的所有兄弟结点和以它们为根的子树
(void) cJSON_Delete(cJSON *item);
cJSON的所有操作都是基于链表的,所以cJSON在使用过程中大量的使用malloc从堆中分配动态内存的,所以在使用完之后,应当及时调用下面的函数,清空cJSON指针所指向的内存,该函数也可用于删除某一条数据:
注意:该函数删除一条JSON数据时,如果有嵌套,会连带删除。
- cJSON提供了格式化打印json的方法:函数将json数据转成字符串
尽量只对没有兄弟结点的节点或根节点调用 cJSON_Delete()
(char *) cJSON_Print(const cJSON *item);
三、cJSON内存问题
在esp32的程序代码中,与服务器通信需要创建大量的cJSON文本格式,因未正确操作cjson,导致内存泄漏,长时间运行程序后程序崩溃,需要严格采用内存申请释放的操作去对esp32的内存空间进行使用。
申请内存: | cJSON_Parse | cJSON_Create | cJSON_Print |
释放内存: | cJSON_Delete | cJSON_Delete | cJSON_free |
四、ESP IDF组件中的cJSON库
找到ESP IDF组件的cJSON库文件夹
ESP-IDF已经将cjson库添加到ESP-IDF编译系统中,只需在esp32的程序代码中正常调用cjson的操作函数即可。
cJSON源码可在路径文件夹下直接打开查看
部分使用代码示例:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "cJSON.h" //cJSON库
cJSON *device_upload_cjson = NULL;
char *access_data = NULL; //接入数据
char *upload_data = NULL; //上传数据
device_upload_cjson = cJSON_CreateObject();
if (device_upload_cjson == NULL)
{
printf("Error before: [%s]\n", cJSON_GetErrorPtr());
return -1;
}
cJSON_AddNumberToObject(device_upload_cjson, "ver", 1);
cJSON_AddNumberToObject(device_upload_cjson, "type", 1);
cJSON_AddNumberToObject(device_upload_cjson, "func", 101);
更多推荐
所有评论(0)