全面详解C语言使用cJSON解析JSON字符[转载]
cJSON对象的实现采用了树形结构,每个对象是树的一个节点,每个节点由cJSON这个结构体组成,对象中的元素也由cJSON这个结构体组成。同一层的对象和元素是双向链表结构,由next和prev指针链接。不同层的对象或元素由child指针链接起来。type表示对象或元素类型,string表示对象或节点的名称。元素的值存储在valuestring, valueint和valuedouble中。cJSON.h中有详细的注释
为什么选择cJSON来解析JSON字符串?因为简洁又简单,而且效率又快,cJSON工程文件也非常简单,仅一个.c文件和一个.h文件!
如果要自己写的话就是重造轮子了,况且效率上也不一定会比cJSON更好!
且文件体积大小不到30k,源代码思路也非常清晰,也非常适合研究。
1 typedef struct cJSON
2 { //cJSON结构体
3 struct cJSON *next,*prev; /* 遍历数组或对象链的前向或后向链表指针*/
4 struct cJSON *child; /* 数组或对象的孩子节点*/
5 int type; /* key的类型*/
6 char *valuestring; /* 字符串值*/
7 int valueint; /* 整数值*/
8 double valuedouble; /* 浮点数值*/
9 char *string; /* key的名字*/
10 } cJSON;
正所谓万丈高楼平地起,先从最简单的开始!
先来介绍四个常用的cJSON函数:
1 cJSON *cJSON_Parse(const char *value);
作用:将一个JSON数据包,按照cJSON结构体的结构序列化整个数据包,并在堆中开辟一块内存存储cJSON结构体
返回值:成功返回一个指向内存块中的cJSON的指针,失败返回NULL
1 cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
作用:获取JSON字符串字段值
返回值:成功返回一个指向cJSON类型的结构体指针,失败返回NULL
1 char *cJSON_Print(cJSON *item);
作用:将cJSON数据解析成JSON字符串,并在堆中开辟一块char*的内存空间存储JSON字符串
返回值:成功返回一个char*指针该指针指向位于堆中JSON字符串,失败返回NULL
1 void cJSON_Delete(cJSON *c);
作用:释放位于堆中cJSON结构体内存
返回值:无
假如说有这样的一个JSON字符串
1 {
2 "test_1":"0"
3 "test_2":"1"
4 "test_3":"2"
5 } //json_string
这是最简单的JSON字符串
我们首先要先将这个字符串打包成cJSON数据格式
1 cJSON* cjson = cJSON_Parse(json_string);
打包后使用if语句或三目表达式判断一下是否将JSON字符串打包成cJSON数据格式
1 if(cjson == NULL)
2 {
3 printf("json pack into cjson error...");
4 }
5 else
6 {//打包成功调用cJSON_Print打印输出
7 printf("%s\r\n",cJSON_Print(cjson));
8 }
9 然后依次获取json字符串中的每个字段的值并打印输出
10 //cJSON_GetObjectltem返回的是一个cJSON结构体所以我们可以通过函数返回结构体的方式选择返回类型!
11 char* test_1_string = cJSON_GetObjectltem(cjson,"test_1")->valuestring;
12 char* test_2_string = cJSON_GetObjectltem(cjson,"test_2")->valuestring;
13 char* test_3_string = cJSON_GetObjectltem(cjson,"test_3")->valuestring;
14 //打印输出
15 printf("%s",*test_1_string);
16 printf("%s",*test_2_string);
17 printf("%s",*test_3_string);
最后别忘记释放内存
1 //delete cjson 2 cJSON_Delete(cjson);
完整代码:
1 #include <stdio.h>
2 #include "cJSON.h"
3
4 int main()
5 {
6 char json_string[] ="{ \"cmd\":12, \
7 \"device\":\"lamp\", \
8 \"power\":1, \
9 \"brightness\":50 \
10 }";
11 //JSON字符串到cJSON格式
12 cJSON* cjson = cJSON_Parse(json_string);
13 //判断cJSON_Parse函数返回值确定是否打包成功
14 if(cjson == NULL)
15 {
16 printf("json pack into cjson error...");
17 }
18 else
19 {//打包成功调用cJSON_Print打印输出
20 printf("%s\r\n",cJSON_Print(cjson));
21 }
22
23 //获取字段值
24 //cJSON_GetObjectltem返回的是一个cJSON结构体所以我们可以通过函数返回结构体的方式选择返回类型!
25 int test_1_string = cJSON_GetObjectItem(cjson,"cmd")->valueint;
26 char* test_2_string = cJSON_GetObjectItem(cjson,"device")->valuestring;
27 int test_3_string = cJSON_GetObjectItem(cjson,"power")->valueint;
28 int test_4_string = cJSON_GetObjectItem(cjson,"brightness")->valueint;
29
30 //打印输出
31 printf("%d\r\n",test_1_string);
32 printf("%s\r\n",test_2_string);
33 printf("%d\r\n",test_3_string);
34 printf("%d\r\n",test_4_string);
35
36 //delete cjson
37 cJSON_Delete(cjson);
38 }
39 是不是很easy?下面来教大家如何使用cJSON解析数组!
40
41 {
42 "test_arr":[{
43 {
44 "test_1":"arr_1",
45 "test_2":"arr_2",
46 "test_3":"arr_3"
47 },
48 {
49 "test_1":"1",
50 "test_2":"2",
51 "test_3":"3"
52 }
53 }]
54 }
在开始前介绍一个函数
1 int cJSON_GetArraySize(cJSON *array);
作用:获取数组成员对象个数
返回值:数组成员对象个数
首先第一步打包
1 cJSON* cjson = cJSON_Parse(json_arr_string);
第二步判断打包是否成功
1 if(cjson == NULL)
2 {
3 printf("cjson error...");
4 }
5 else
6 {//打包成功调用cJSON_Print打印输出
7 printf("%s\r\n",cJSON_Print(cjson));
8 }
第三步获取数组对象
1 cJSON* test_arr = cJSON_GetObjectltem(cjson,"test_arr");
第四步获取数组对象个数便于循环
1 int arr_size = cJSON_GetArraySize(test_arr);//return arr_size 2
第五步获取test_arr数组对象孩子节点
1 cJSON* arr_item = test_arr->child;//子对象
第六步循环获取数组下每个字段的值并使用cJSON_Print打印:
1 for(int i = 0;i <=(arr_size-1)/*0*/;++i)
2 {
3 printf("%s\r\n",cJSON_Print(cJSON_GetObjectItem(arr_item,"test_1")));
4 printf("%s\r\n",cJSON_Print(cJSON_GetObjectItem(arr_item,"test_2")));
5 printf("%s\r\n",cJSON_Print(cJSON_GetObjectItem(arr_item,"test_3")));
6 arr_item = arr_item->next;//下一个子对象
7 }
最后别忘记释放
1 cJSON_Delete(cjson);
完整代码:
1 #include <stdio.h>
2 #include "cJSON.h"
3
4 int main()
5 {
6 char json_arr_string[]="{\"test_arr\":[{\"test_1\":\"arr_1\",\"test_2\":\"arr_2\",\"test_3\":\"arr_3\"},{\"test_1\":\"1\",\"test_2\":\"2\",\"test_3\":\"3\"}]}";
7
8 cJSON* cjson = cJSON_Parse(json_arr_string);
9 if(cjson == NULL)
10 {
11 printf("cjson error...\r\n");
12 }
13 else
14 {//打包成功调用cJSON_Print打印输出
15 printf("%s\r\n",cJSON_Print(cjson));
16 }
17 cJSON* test_arr = cJSON_GetObjectItem(cjson,"test_arr");
18 int arr_size = cJSON_GetArraySize(test_arr);//return arr_size 2
19 cJSON* arr_item = test_arr->child;//子对象
20
21 for(int i = 0;i <=(arr_size-1)/*0*/;++i)
22 {
23 printf("%s\r\n",cJSON_Print(cJSON_GetObjectItem(arr_item,"test_1")));
24 printf("%s\r\n",cJSON_Print(cJSON_GetObjectItem(arr_item,"test_2")));
25 printf("%s\r\n",cJSON_Print(cJSON_GetObjectItem(arr_item,"test_3")));
26 arr_item = arr_item->next;//下一个子对象
27 }
28 cJSON_Delete(cjson);
29 }
————————————————
版权声明:本文为CSDN博主「void*_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_36612961/article/details/90768404
全面详解C语言使用cJSON解析JSON字符[转载]的更多相关文章
- Linux 命令详解(十一)Shell 解析 json命令jq详解
前言 在自动化部署中涉及到shell脚本需要动态读取很多配置文件,最好是json格式. 更多jq信息: http://stedolan.github.io/jq/manual/ 一.根据key获取va ...
- 详解go语言的array和slice 【二】
上一篇已经讲解过,array和slice的一些基本用法,使用array和slice时需要注意的地方,特别是slice需要注意的地方比较多.上一篇的最后讲解到创建新的slice时使用第三个索引来限制sl ...
- 详解 Go 语言中的 time.Duration 类型
swardsman详解 Go 语言中的 time.Duration 类型swardsman · 2018-03-17 23:10:54 · 5448 次点击 · 预计阅读时间 5 分钟 · 31分钟之 ...
- SpringBoot Profile使用详解及配置源码解析
在实践的过程中我们经常会遇到不同的环境需要不同配置文件的情况,如果每换一个环境重新修改配置文件或重新打包一次会比较麻烦,Spring Boot为此提供了Profile配置来解决此问题. Profile ...
- 详解Go语言调度循环源码实现
转载请声明出处哦~,本篇文章发布于luozhiyun的博客: https://www.luozhiyun.com/archives/448 本文使用的go的源码15.7 概述 提到"调度&q ...
- 使用cJSON解析JSON
cJSON获取数组元素的每个值 { "operType": 0x5, "field": ["time","matchRule&qu ...
- Rserve详解,R语言客户端RSclient【转】
R语言服务器程序 Rserve详解 http://blog.fens.me/r-rserve-server/ Rserve的R语言客户端RSclient https://blog.csdn.net/u ...
- Android中measure过程、WRAP_CONTENT详解以及 xml布局文件解析流程浅析
转自:http://www.uml.org.cn/mobiledev/201211221.asp 今天,我着重讲解下如下三个内容: measure过程 WRAP_CONTENT.MATCH_PAREN ...
- C语言创建及解析Json的使用法则
参考原文:http://blog.csdn.net/xukai871105/article/details/33013455 JSON(JavaScriptObject Notation)是一种轻量级 ...
- 详解Go语言I/O多路复用netpoller模型
转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com 本文使用的go的源码15.7 可以从 Go 源码目录结构和对应代码文件了解 Go 在不同 ...
随机推荐
- vue ssr error: TypeError: Cannot read property 'replace' of undefined
在开发vue ssr应用时, yarn build yarn start 之后启动正常: info Server running at: http://0.0.0.0:6606 在访问页面时,发现页 ...
- Pytorch 手写数字识别 深度学习基础分享
本篇是一次内部分享,给项目开发的同事分享什么是深度学习.用最简单的手写数字识别做例子,讲解了大概的原理. 手写数字识别 展示首先数字识别项目的使用.项目实现过程: 训练出模型 准备html手写板 fl ...
- uni-app小程序(快手、抖音)getCurrentPages使用坑位记录2
前情 uni-app是我比较喜欢的跨平台框架,它能开发小程序/H5/APP(安卓/iOS),重要的是对前端开发友好,自带的IDE让开发体验也挺棒的,现公司项目就是主推uni-app,我主要负责抖音和快 ...
- vs2017 opencv 编译错误 error C2665: “exp”: 3 个重载中没有一个可以转换所有参数类型
编译错误 - error C2665: "exp": 3 个重载中没有一个可以转换所有参数类型,在GenericPacketMath.h文件, 是因为使用了Eigen3.4库,只要 ...
- 使用 Web Compiler 2022+
使用 Web Compiler 2022+ Web Compiler 2022+ for Visual Studio 2022 Web Compiler for Visual Studio 2019 ...
- WSLg 中文输入法 fcitx5
随着 Win11 22H2 和 WSLg 的推出,很多开启输入法的教程都过时了.记录一下最新实践: WSL 安装 Ubuntu 后,安装中文语言 sudo /usr/bin/gnome-languag ...
- GOLAND-激活码-20230309
33MEHOB8W0-eyJsaWNlbnNlSWQiOiIzM01FSE9COFcwIiwibGljZW5zZWVOYW1lIjoiUG9saXRla25payBNZXJsaW1hdSBNZWxha ...
- ERROR: manifest for hyperledger/fabric-orderer:latest not found
In docker command # pull to local before using itdocker pull hyperledger/fabric-orderer:x86_64-1.0.0 ...
- Qt编写地图综合应用20-多浏览器内核
一.前言 本人写Qt程序这么多年,比较喜欢支持多个Qt版本,尤其是钟情于支持任意Qt版本+任意系统+任意编译器,这句话说起来简单其实实现起来就不容易了,首先你得有个很多版本的测试环境,起码十几个Qt环 ...
- Type of the default value for 'data' prop must be a function的解决方法
Type of the default value for 'data' prop must be a function的解决方法 问题现象 在写形如prop: {type: Array; defau ...