电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
cJSON基础介绍与代码测试
分 享
扫描二维码分享
cJSON基础介绍与代码测试
cJSON
码农爱学习
关注
发布时间: 2021-04-12
丨
阅读: 607
C语言开发中,你使用过cJSON吗 在介绍cJSON之前,首先来认识一下JSON... # JSON是什么 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。JSON 使用 Javascript语法来描述数据对象,但是 JSON 仍然独立于语言和平台。 ## JSON 基本语法 - 数据以 **`key :value`** (名称/值) 的形式存在 - 数据由逗号 **`,`** 分隔 - 大括号 **`{}`** 保存对象 - 中括号 **`[]`** 保存数组,数组可以包含多个对象 例如: ```json { name : C Primer pluse, pages : 626 } ``` ## JSON值(value)的类型 ```c /@@* cJSON Types: */ #define cJSON_False 0 #define cJSON_True 1 #define cJSON_NULL 2 #define cJSON_Number 3 #define cJSON_String 4 #define cJSON_Array 5 #define cJSON_Object 6 ``` - 逻辑值(true 或 false) ```json {"flag":true} ``` - null ```json {"name":null} ``` - **NUMBER 数字**(整数或浮点数) ```json {"pages":200, "price":35.00} ``` - **STRING 字符串**(在双引号`""`中) ```json {"book":"C Primer pluse"} ``` - **ARRAY 数组**(在中括号`[]`中) ```json [ {"name":"C Primer pluse", "author":"Stephen Prata"}, {"name":"C程序设计", "author":"谭浩强"}, {"name":"C陷阱与缺陷", "author":"Andrew Koenig"} ] ``` - **OBJECT 对象**(在大括号`{}`中) ```json {"name":"C Primer pluse", "author":"Stephen Prata"} ``` 当然对象内部也可以是数组,如: ```json { "books":[ {"name":"C Primer pluse", "author":"Stephen Prata"}, {"name":"C程序设计", "author":"谭浩强"}, {"name":"C陷阱与缺陷", "author":"Andrew Koenig"} ] } ``` 对象 **books** 内部是一个数组,该数组又包含了三个对象 # cJSON又是个啥 cJSON是一个基于C的JSON解析库,这个库非常简短,源码内容只包含一个`cJSON.h`头文件和一个`cJSON.c`源文件,支持JSON的解析和封装,需要调用时,只需要`#include "cJSON.h"`就可以使用了。 cJSON源文件开源项目地址:
。 # cJSON编程实例 ## 例子1 先演示一个最简单的JSON数据,如何使用cJSON库来解析。 用于测试JSON数据,我们先用一个char型的字符串了保存,注意,由于JSON对象的key和value都需要使用引号(数值或逻辑型value除外),所以,**使用C语言的字符串来保存JSON数据,在遇到引号时,要加反斜杠来转义**。 解析JSON数据时,首先要调用 `cJSON_Parse()` 这个函数,将JSON数据解析为 `cJSON` 型的对象: ```c cJSON *srcJsonData = cJSON_Parse(jsonData); ``` 然后就可以使用cJSON库中提供的各种函数来操作这个对象。比如 : ```c value = cJSON_GetObjectItem(srcJsonData,"name"); ``` 就是通过 `cJSON_GetObjectItem()` 来获取JSON数据中的一项数据,并通过指定key的方式来获取对应的value。 整个测试程序如下: ```c #include
#include
#include "cJSON.h" void main(void) { char jsonData[] = "{\"name\":\"C Primer pluse\",\"pages\":626}"; cJSON *srcJsonData = cJSON_Parse(jsonData); if(!srcJsonData) { printf("Error:%s\r\n",cJSON_GetErrorPtr()); } else { /@@*获取Json数据的内容*/ cJSON *value; value = cJSON_GetObjectItem(srcJsonData,"name");/@@*通过key来获取value*/ if(value->type == cJSON_String)/@@*字符串型的value*/ { printf("书名:%s\r\n",value->valuestring); } value = cJSON_GetObjectItem(srcJsonData,"pages");/@@*通过key来获取value*/ if(value->type == cJSON_Number)/@@*数值型的value*/ { printf("页数:%d\r\n",value->valueint); } cJSON_Delete(srcJsonData); } } ``` 运行结果: ```shell 书名:C Primer pluse 页数:626 -------------------------------- Process exited after 0.01452 seconds with return value 0 请按任意键继续. . . ``` ## 例子2 上面是一个最基本的测试程序,JSON数据也是直接通过C语言的字符串保存的。 实际的使用中,JSON数据的内容较为庞大,再使用C语言的字符串来保存,则会及其麻烦(想想那一堆反斜杠)。 所以,**一般都是使用文件的形式来保存JSON数据**。 准备一个原始数据用于测试,如下面的data.txt: ```json { "class":"C语言书籍", "books":[{ "name":"C Primer pluse", "author":"Stephen Prata", "publishing":"人民邮电出版社" }, { "name":"C程序设计", "author":"谭浩强", "publishing":"清华大学出版社" }, { "name":"C陷阱与缺陷", "author":"Andrew Koenig", "publishing":"人民邮电出版社" }] } ``` 先来分析下这个JSON数据的结构: - 最外面的大括号,表示这个一个JSON对象 - 对象里面有2个数据,key1是class,key2是books - books的value又是一个中括号表示的数组 - 数组内又包含了3个对象,每个对象有3个数据,key1是name,key2是author,key3是publishing 解析这种JSON文件,使用要使用 `fopen()` 来打开这个文件: ```c FILE *fp = fopen("data.txt", "r"); ``` 这里还要使用`fseek()`和`ftell()`来计算文件的大小,目的是用于后面的分配内存时指定大小。 然后使用`fread()`将文件内存读入内存中分配的buf中: ```c fread(buf, fileSize, sizeof(char), fp); ``` 接着,还是使用`cJSON_Parse()` 将JSON数据解析为 `cJSON` 型的对象 ```c cJSON *srcJsonData = cJSON_Parse(buf); ``` 然后就可以使用cJSON库中提供的各种函数来操作这个对象了。 这次会用到`cJSON_GetObjectItem()`、`cJSON_GetArrayItem()` 、`cJSON_GetArraySize()`、`cJSON_Print()`等函数。 注意是使用完`cJSON_Print()`后,要使用`free()`来释放。 具体的测试程序如下: ```c #include
#include
#include
#include "cJSON.h" void main(void) { /@@*打开JSON文件*/ FILE *fp = fopen("data.txt", "r"); if(fp == NULL) { return; } /@@*计算文件大小*/ int fileSize; fseek(fp, 0, SEEK_END);/@@*先移到文件末尾*/ fileSize = ftell(fp);/@@*计算文件的大小*/ printf("fileSize: %d\r\n", fileSize); fseek(fp, 0, SEEK_SET);/@@*再移到文件开头*/ /@@*根据文件大小分配内存,并读取文件到内存*/ char *buf = (char *)malloc(fileSize * sizeof(char)); memset(buf, 0, fileSize); int ret = fread(buf, fileSize, sizeof(char), fp); if(ret == -1) { fclose(fp); return; } printf("%s\r\n",buf); fclose(fp); /@@*把该字符串数据转成JSON数据*/ cJSON *srcJsonData = cJSON_Parse(buf); free(buf); if(srcJsonData == NULL) { printf("err\r\n"); return; } cJSON *value; /@@*根据key值(class)获取对应的value*/ value = cJSON_GetObjectItem(srcJsonData, "class"); if(value == NULL) { printf("GetObjectItem err\r\n"); cJSON_Delete(srcJsonData); return; } /@@*把value转成字符串输出*/ char *data = cJSON_Print(value); printf("class=%s\r\n",data); free(data); /@@*根据key值(books)获取对应的value*/ value = cJSON_GetObjectItem(srcJsonData, "books"); if(value == NULL) { printf("GetObjectItem err\r\n"); cJSON_Delete(srcJsonData); return; } /@@*获取该数组对象的大小*/ int len = cJSON_GetArraySize(value); printf("books data: len=%d\r\n",len); /@@*访问books中的每一项*/ int i = 0; for(i=0; i
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
0
)
码农爱学习
关注
评论
(0)
登录后可评论,请
登录
或
注册
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交