高级时钟项目(2)Json文件解析学习---C语言版本

笔者来介绍一下json文件解析

1、背景介绍

笔者在获取天气数据的时候,是通过MCU的WIFI去获取,但是获取到的数据json数据,需要解析,C语言没那么解析库,所以就需要找一些开源的解析库。
在这里插入图片描述
在这里插入图片描述

笔者找到cjson这个适用于C语言的解析json库,一个.c,一个.h,非常简单,没有其他任何依赖,直接使用就好

2、json数据解析学习使用

2.1 解析使用

介绍一下正常的json数据解析,一般就是三个接口,
第一步,调用解析接口,将总的json数据进行解析,
第二步,就是获取json的里面的字段,一级一级的去获取item数据,就可以获取到数据,一般都是字符串
第三步,获取完成之后,记得delete,因为是通过堆来获取空间大小的。

cJSON *cJSON_Parse(const char *value) ;
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
void cJSON_Delete(cJSON *c);
	char json2[] = "{\"success\":\"1\",\"result\":{\"timestamp\":\"1668090740\",\"datetime_1\":\"2022 - 11 - 10 22:32 : 20\",\"datetime_2\":\"2022年11月10日 22时32分20秒\",\"week_1\":\"4\",\"week_2\":\"星期四\",\"week_3\":\"周四\",\"week_4\":\"Thursday\"}}";cJSON *root = cJSON_Parse(json2);if (root == 0){printf("error\n");return;}printf("%s\n", "有格式的方式打印Json:");printf("%s\n\n", cJSON_Print(root));cJSON *success = cJSON_GetObjectItem(root, "success");if (success == 0)return;printf("success name:\n\t%s\nsuccess value:\n\t%s\n", success->string, success->valuestring);cJSON *result = cJSON_GetObjectItem(root, "result");cJSON *timestamp = cJSON_GetObjectItem(result, "timestamp");printf("timestamp value:\n\t%s\n", timestamp->valuestring);cJSON *datetime_1 = cJSON_GetObjectItem(result, "datetime_1");printf("datetime_1 value:\n\t%s\n", datetime_1->valuestring);cJSON *datetime_2 = cJSON_GetObjectItem(result, "datetime_2");printf("datetime_1 value:\n\t%s\n", datetime_2->valuestring);cJSON *week_1 = cJSON_GetObjectItem(result, "week_1");printf("timestamp value:\n\t%s\n", week_1->valuestring);cJSON *week_2 = cJSON_GetObjectItem(result, "week_2");printf("timestamp value:\n\t%s\n", week_2->valuestring);cJSON *week_3 = cJSON_GetObjectItem(result, "week_3");printf("timestamp value:\n\t%s\n", week_3->valuestring);cJSON *week_4 = cJSON_GetObjectItem(result, "week_4");printf("timestamp value:\n\t%s\n", week_4->valuestring);cJSON_Delete(root);

在这里插入图片描述

初步来看一下解析里面的实现:

cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)
{cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
  • 就是从子节点里面找到匹配的“名称”,如果子节点为空,则直接退出,返回NULL了,
  • 如果不为空,则cJSON_strcasecmp就是字符串匹配,没有匹配到,则进行next,这里就有疑问了,为什么是next,而不是child的,这是因为父节点里面会有很多项,你要找父节点中匹配的子节点,如果你要找子节点里面的子节点的项,就是child。
  • 从下面的result就能看出来,先找child,然后找child以及child的next,以及next的next。

在这里插入图片描述

2.2 json数组解析

json格式里面,带[ ]就是数组的,需要用到获取数组size的接口。

char json3[] = "{\"results\":[{\"location\":{\"id\":\"WTW3SJ5ZBJUY\",\"name\":\"上海\",\"country\":\"CN\",\"path\":\"上海, 上海, 中国\",\"timezone\":\"Asia / Shanghai\",\"timezone_offset\":\" + 08:00\"},\"now\":{\"text\":\"晴\",\"code\":\"1\",\"temperature\":\"26\"},\"last_update\":\"2023 - 09 - 06T23:40 : 13 + 08 : 00\"}]}";
int    cJSON_GetArraySize(cJSON *array);
cJSON *cJSON_GetArrayItem(cJSON *array,int item);

刚开始的时候,我按照上面正常数据的去解析,发现始终解析出来就是空的,很奇怪,

  • 第一步,cJSON_Parse解析root
  • 第二步,获取root下面的results
  • 第三步,获取到results之后,到[ ]了,然后我就开始获取数组size,但是结果返回1,明显不对,总共有3个,
    在这里插入图片描述
cJSON* root = cJSON_Parse(json3);if (root == 0){printf("error\n");return;}printf("%s\n", "有格式的方式打印Json:");printf("%s\n\n", cJSON_Print(root));cJSON* results = cJSON_GetObjectItem(root, "results");if (0 == results){return;}int array_size = cJSON_GetArraySize(results );printf("item size=%d\r\n", array_size);

然后我就开始调试,VS有个好处就是调试非常方便,断点处的数据也很清晰。
在这里插入图片描述
通过断点调试来看,我这样的写法也是有问题的,需要继续深入这个结构体去查看,发现需要继续下一层,通过回去NULL的子节点,然后终于出现location了,说明这一层才是getsize的节点。

在这里插入图片描述
然后我又紧接着去看子节点,发现是该节点里面的数据了,并不是同一级别的数据,然后我看到了next,果然是在这个里面找到了“now”,然后接着找next,找到了“last_update”,说明这样解析的顺序才是正确的。
在这里插入图片描述
在这里插入图片描述

下面给出完整的实例代码。

char json3[] = "{\"results\":[{\"location\":{\"id\":\"WTW3SJ5ZBJUY\",\"name\":\"上海\",\"country\":\"CN\",\"path\":\"上海, 上海, 中国\",\"timezone\":\"Asia / Shanghai\",\"timezone_offset\":\" + 08:00\"},\"now\":{\"text\":\"晴\",\"code\":\"1\",\"temperature\":\"26\"},\"last_update\":\"2023 - 09 - 06T23:40 : 13 + 08 : 00\"}]}";cJSON* root = cJSON_Parse(json3);if (root == 0){printf("error\n");return;}printf("%s\n", "有格式的方式打印Json:");printf("%s\n\n", cJSON_Print(root));cJSON* results = cJSON_GetObjectItem(root, "results");if (0 == results){return;}cJSON* results1 = cJSON_GetObjectItem(results, NULL);//printf("results name:%s results value:%s\r\n", results->string, results->valuestring);int array_size = cJSON_GetArraySize(results1);printf("item size=%d\r\n", array_size);cJSON* location = cJSON_GetArrayItem(results1, 0);printf("location value:%p %s\r\n", location, location->valuestring);if (0 == location){return;}cJSON* id = cJSON_GetObjectItem(location, "id");printf("id value:%p %s\r\n", id, id->valuestring);

在这里插入图片描述

int    cJSON_GetArraySize(cJSON *array)							{cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
cJSON *cJSON_GetArrayItem(cJSON *array,int item)				{cJSON *c=array->child;  while (c && item>0) item--,c=c->next; return c;}

来看一下数组的实现:

  • 这个主要就是看一下父节点下面有几个子节点,然后去按照节点顺序去访问。
    在这里插入图片描述

2.3 注意事项

  • cjson在C代码空间里面是通过mallco获取ram空间的,所以需要记得堆的空间开大一点,不然无法解析,直接返回NULL。
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/90375.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue - 组件递归

目录 组件递归子组件父组件 组件递归 当要渲染一个目录时,因为可能有嵌套数据,并且组件的层级未知,可以使用组件递归来解决 注意点: 1,使用递归时必须提供 name,也就是通过组件的 name 递归自己。 2&am…

Anaconda添加channels后出现unexpected urllib3 DEBUG logging from conda-build

1.问题描述 anaconda更新之后添加channels后出现bug: (base) ~/zlib-feedstock % conda build recipe 2>&1 | tee out ... INFO:conda_build.metadata:Attempting to finalize metadata for libzlib DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1):…

【c语言】通讯录【动态版本:有排序和文件操作】

目录 一、通讯录定义 二、通讯录的实现 1、test.c中菜单的实现 2、通讯录的创建逻辑 3、初始化 4、检查容量和添加 5、查找 6、删除功能 7、修改功能 8、打印 9、查找并打印 10、qsort排序 11、摧毁 12、保存数据到文件 13、从文件中读数据 完整代码: 一、通讯录定…

ABC310D Peaceful Teams

ABC310D Peaceful Teams 洛谷[ABC310D] Peaceful Teams 题目大意 有 n n n个运动员以及 m m m对数,每对数为 A i A_i Ai​和 B i B_i Bi​,表示 A i A_i Ai​和 B i B_i Bi​不能分在同一小组。你需要将这些人分为 t t t个小组,每个小组不…

【C++进阶(六)】STL大法--栈和队列深度剖析优先级队列适配器原理

💓博主CSDN主页:杭电码农-NEO💓   ⏩专栏分类:C从入门到精通⏪   🚚代码仓库:NEO的学习日记🚚   🌹关注我🫵带你学习C   🔝🔝 栈和队列 1. 前言2. 栈和队列的接口函数熟悉3. …

《淘宝电商业务场景》API接口教程获得淘口令真实url

淘口令API接口的本质就是一款调用相关技术的应用程序接口,同时也是一种通过互联网传输数据的方式,可以实现各种各样的应用场景。比如企业运用在分享商品页面的过程中,可以简单组成一个淘口令,以便于分享淘口令。淘口令解析API接口…

java easyexcel 导出多级表头

maven <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>${easyexcel.version}</version> </dependency> 导出行的对象 import com.alibaba.excel.annotation.ExcelIgnore; import …

基础算法--KMP字符串

KMP 算法是一个快速查找匹配串的算法&#xff0c;它的作用其实就是本题问题&#xff1a;如何快速在「原字符串」中找到「匹配字符串」。 在朴素解法中&#xff0c;不考虑剪枝的话复杂度是 O(m∗n) 的&#xff0c;而 KMP 算法的复杂度为 O(mn)。 KMP 之所以能够在O(mn) 复杂度内…

leetCode 213. 打家劫舍 II 动态规划 房间连成环怎么偷呢?

213. 打家劫舍 II - 力扣&#xff08;LeetCode&#xff09; 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋&#xff0c;每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 &#xff0c;这意味着第一个房屋和最后一个房屋是紧挨着的。同时&#xff0c;相邻的房屋装…

websocket连接实例

websocket连接 此篇websocket是最简单的运用&#xff0c;虽然简单&#xff0c;但也是需要注意 还有其它方法货协议&#xff0c;比如socket.js等。今天时间不充裕虽然例子都写好了&#xff0c;下次更新websocket所有相关的东西。提前想了解的&#xff0c;可私信 前端 var webs…

Spring Cloud Stream Kafka(3.2.2版本)使用

问题 正在尝试只用Spring Cloud Stream Kafka。 步骤 配置 spring:cloud:function:definition: project2Building stream:kafka:binder:brokers: xxxx:9002configuration:enable.auto.commit: falsesession.timeout.ms: 30000max.poll.records: 30allow.auto.create.top…

PHP Web 开发基础

PHP是动态类型的Web开发的脚本语言&#xff0c;PHP以页面文件作为加载和运行的单元&#xff0c;PHP现在有了Composer作为开发包管理。 1.使用Composer管理依赖 自从.NET开发用了Nuget管理程序集依赖&#xff0c;我就再也离不开它了&#xff0c;幸亏Java中也有Maven管理jar包&…

如何定时备份使用Docker构建的MySQL容器中的数据库

&#x1f468;&#x1f3fb;‍&#x1f4bb; 热爱摄影的程序员 &#x1f468;&#x1f3fb;‍&#x1f3a8; 喜欢编码的设计师 &#x1f9d5;&#x1f3fb; 擅长设计的剪辑师 &#x1f9d1;&#x1f3fb;‍&#x1f3eb; 一位高冷无情的编码爱好者 大家好&#xff0c;我是 DevO…

PIE:1979-2018年中国气温数据产品(空间分辨率为0.1º)

简介 中国气温数据产品包含1979-2018年期间中国的近地表气温数据&#xff08;单位为摄氏度&#xff09;&#xff0c;时间分辨率为每日&#xff0c;空间分辨率为0.1。本产品集成了再分析数据&#xff08;ERA5、CMFD&#xff09;、遥感数据&#xff08;MODIS&#xff09;、原位数…

php eayswoole node axios crypto-js 实现大文件分片上传复盘

不啰嗦 直接上步骤 步骤1.开发环境配置 项目需要node.js 做前端支撑 官网下载地址&#xff1a; http://nodejs.cn/download/ 根据自己需要下载对应的版本,我下载的是windows系统64位的版本。 包下载好后 进行安装&#xff0c;安装步骤在此省略... 测试是否安装成功 …

蓝海彤翔亮相2023新疆网络文化节重点项目“新疆动漫节”

9月22日上午&#xff0c;2023新疆网络文化节重点项目“新疆动漫节”&#xff08;以下简称“2023新疆动漫节”&#xff09;在克拉玛依科学技术馆隆重开幕&#xff0c;蓝海彤翔作为国内知名的文化科技产业集团应邀参与此次活动&#xff0c;并在美好新疆e起向未来动漫展映区设置展…

C#生成自定义海报

安装包 SixLabors.ImageSharp.Drawing 2.0 需要的字体&#xff1a;宋体和微软雅黑 商用的需要授权如果商业使用可以使用方正书宋、方正黑体&#xff0c;他们可以免费商用 方正官网 代码 using SixLabors.Fonts; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Draw…

python切分字符串

在Python中&#xff0c;您可以使用不同的方法来切分字符串&#xff0c;具体取决于您的需求和字符串的结构。以下是一些常见的方法&#xff1a; 使用split()方法&#xff1a; split()方法允许您根据指定的分隔符将字符串切分成子字符串&#xff0c;并返回一个包含这些子字符串的…

使用SPY++查看窗口信息去排查客户端UI软件问题

目录 1、使用SPY查看窗口的信息 2、使用SPY查看某些软件UI窗口用什么UI组件实现的 2.1、查看海康视频监控客户端安装包程序 2.2、查看华为协同办公软件WeLink 2.3、查看字节协同办公软件飞书 2.4、查看最新版本的Chrome浏览器 2.5、查看小鱼易连视频会议客户端软件 2.6…

C/S架构学习之UDP服务器

UDP服务器的实现流程&#xff1a;一、创建用户数据报套接字&#xff08;socket函数&#xff09;&#xff1a;通信域选择IPV4网络协议、套接字类型选择数据报式&#xff1b; int sockfd socket(AF_INET,SOCK_DGRAM,0); 二、填充服务器的网络信息结构体&#xff1a;1.定义网络信…