前言
在STM32OTA例程中,设备端(STM32F769探索板)与云端交换数据使用的是JSON格式。在本篇文章中,将对JSON格式以及cJSON的使用及注意事项进行说明。
JSON格式
JSON(JavaScriptObjectNotation)是一个轻量级的数据交换格式。既便于开发者读写,也便于机器分析和构建。它独立于开发语言,是一种文本格式,很适用描述在各个系统间交换的数据。
JSON格式的数据看起来就像下面这个样子:
这个JSON数据描述的是Room1的LED灯状态以及温度值。它由一组“名称(key)”以及对应的“值(value)”组成。“名称”和“值”之间由“:”分开。各组“名称:值”对之间由“,”符号进行分割。
cJSON的使用
针对不同的开发语言,网上有很多JSON的实现,demo里使用的是cJSON,版本1.6。它的源码可以在
https://github.com/DaveGamble/cJSON上下载。
01将cJSON添加到工程
cJSON只有一个C文件cJSON.c和一个头文件cJSON.h。所以只需要将这两个文件拷贝到工程文件夹中,并将cJSON.c添加到工程中就可以了。
02数据结构
cJSON中使用下面的数据结构来表示JSON数据
*next和*prev指针可以用来遍历“矩阵”或者“对象”类型的JSON数据链表;这两种类型的JSON数据还会有一个子数据指针*child
type:表示该JSON数据的类型,比如数字,字符串、矩阵、对象等
*valuestring,valueint,valuedouble和*string指针分别指向该JSON数据类型具体的值,视其类型而定。
03使用cJSON生成JSON数据
下面我们看看如何使用cJSON来生成下面的数据:
见下面的代码:
现在就已经在cJSON中,构件好了和前面的数据对应的数据结构。但现在这个数据结构还不能发送出去,需要调用cJSON_Print将其打印成串行的数据,存放在buffer中,以便后面进行发送。
cJSON_Print执行的时候会向系统申请一段内存来保存串行化了的数据,并返回其指针。这里一定要注意的是,cJSON_Print中申请的内存,一定要记得释放(cJSON的代码中不会自动去做释放动作),否则就会出现内存泄漏。
通过cJSON_CreateObject创建的对象,也需要调用cJSON_Delete来进行删除并释放占用的内存。否则也会出现内存泄漏。见下面的代码:
仔细的同学可能会发现为什么调用了两次cJSON_CreateObject,但只看到释放了其中的device_obj。这里也是需要注意的一个地方,从前面的代码中,我们可以看到,reported_obj最终是作为子对象添加到了device_obj中,所以在删除device_obj时,cJSON_Delete会自动删除device_obj中所有的子对像,故而不需要再调用cJSON_Delete对reported_obj进行删除。
04使用cJSON解析JSON数据
可以通过cJSON_Parse()函数来解析接收到的JSON数据,cJSON_Parse()函数会对数据进行解析,并申请一段内存保存解析后的cJSON的数据结构,并返回指针。
通过cJSON_GetObjectItem()函数可以获取解析后的cJSON数据结构中的第一级子对象。
使用cJSON_Parse()后,切记也一定要通过cJSON_Delete释放之前所申请的内存。
下面代码是对收到的JSON数据的解析过程。收到的数据内容为:
总结
cJSON代码量不大,用起来也方便。使用的时候一定要注意前面提到对使用完的内存空间进行释放。否则会造成内存泄漏。