前言
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。JSON在互联网相关开发中用得很多,在我们嵌入式中用得也不少。最近在项目中就有用到,用起来很方便。
简单的JSON格式数据如:
{ "name": "xxx", "num": xxx, "c_score": xxx}
这里我们需要知道一个概念:键值对。比如:
"name": "xxx"
像这样子的就是一对键值对。
当我们作为发送方时,我们要把xxx这些有用的数据组合成JSON格式的数据发送给接收方;当我们作为接收方时,我们需要从这一堆JSON数据中解析出xxx这些有用的数据拿来使用。简单的JSON数据,我们使用C语言的一些字符串操作相关的库函数也是可以做到组包和解析的,但是一些稍微复杂一点的JSON,可能就没那么好操作了。
这时候我们可以借助一个第三方库——cJSON库,可以很方便来做数据组包及解析。
cJSON库仓库地址:
https://github.com/DaveGamble/cJSON.git
或者
https://gitee.com/mirrors/cJSON.git
下面我们通过实例来分享使用cJSON库来做数据组包及数据解析。
组包、解析示例
1、确定协议数据
在实际开发中,要把JSON数据作为通信的数据,自然要先确定通信双方要交互的数据有哪些,如有需要还需编写形成协议文档。协议文档包含要传输的数据,数据类型等信息。比如:
2、组JSON数据包示例
从控制台输入一些学生信息,组合成字符串格式的JSON数据包,然后再输出至控制台。
操作示例:
首先,我们先从仓库下载cJSON源码,文件夹内容如:
我们只需要把cJSON.c、cJSON.h两个文件复制到我们工程的根目录下就可以使用,如:
从cJSON.h可以看到其给我们提供了很多接口:
本例中我们重点关注如下几个接口即可:
cJSON_CreateObject:创建JSON对象,{}扩起来的cJSON_CreateString:创建字符串cJSON_CreateNumber:创建int类型数据cJSON_AddItemToObject:添加到JSON对象中cJSON_Print:呈现为标准的JSON格式cJSON_PrintUnformatted:呈现为去掉空格的JSON格式cJSON_Delete:JSON对象删除,做一些释放内存的工作
我们创建的的组包函数如下:
static char *StudentsData_Packet(pStudentDef _Stu){ char *res_string = NULL; // 返回值 cJSON *name = NULL; // 名字 cJSON *num = NULL; // 学号 cJSON *c_score = NULL; // C语言分数 /* 创建一个JSON对象,{}扩起来 */ cJSON *obj = cJSON_CreateObject(); if (obj == NULL) { goto end; } /* 创建 "name": "xxx" 键值对 */ name = cJSON_CreateString(_Stu->name); if (name == NULL) { goto end; } cJSON_AddItemToObject(obj, "name", name); /* 创建 "num": 207 键值对 */ num = cJSON_CreateNumber(_Stu->num); if (name == NULL) { goto end; } cJSON_AddItemToObject(obj, "num", num); /* 创建 "c_score": 95 键值对 */ c_score = cJSON_CreateNumber(_Stu->c_score); if (name == NULL) { goto end; } cJSON_AddItemToObject(obj, "c_score", c_score); res_string = cJSON_Print(obj); // 呈现为JSON格式 // res_string = cJSON_PrintUnformatted(obj); // 呈现为无格式 if (res_string == NULL) { fprintf(stderr, "Failed to print monitor."); }/* 异常情况统一Delete(free) */end: cJSON_Delete(obj); return res_string;}
详细解释见注释。我们重点看一下cJSON_Print与cJSON_PrintUnformatted这两个接口。这两个接口的差别就是组合成的JSON数据是否有空格。我们通过JSON相关的在线网站看一下其区别:
https://www.sojson.com/json/json_online.html
有空格的JSON数据,即用cJSON_Print时的效果为:
无空格的JSON数据,即用cJSON_PrintUnformatted时的效果为:
如果想要输出查看时,当然是用cJSON_Print比较方便查看;如果是实际通信时,当然是用cJSON_PrintUnformatted会比较好,毕竟去掉空格就可以减小一定程度的通信负担。
完整代码:
/* 作者:ZhengN 公众号:嵌入式大杂烩*/#include #include #include #include "cJSON.h"#define STU_NAME_LEN 32/* 学生结构体 */typedef struct _Student{ char name[STU_NAME_LEN]; // 名字 int num; // 学号 int c_score; // C语言分数}StudentDef, *pStudentDef;/* 内部函数声明 */static char *StudentsData_Packet(pStudentDef _Stu);/********************************************************************************************************** 函数: main**------------------------------------------------------------------------------------------------------** 参数: ** 说明: ** 返回: ********************************************