学习笔记——天气数据解析1(JSON格式数据)
2018-02-01 01:13
357 查看
一、基本介绍
最近做了个基于STM32的天气预报系统。通过wifi模块从心知天气(http://www.seniverse.com/)获取天气数据,其天气数据的格式为JSON格式,对于JSON格式数据的学习,可以参考博文:http://blog.csdn.net/xukai871105/article/details/32346797(这一篇为JSON格式详解)、http://blog.csdn.net/lintax/article/details/50993958(这一篇介绍如何使用cJSON库解析JSON格式数据)和http://blog.csdn.net/taiyang1987912/article/details/49862141(这一篇为cJSON库的介绍)。cJSON库的下载地址为:http://sourceforge.net/projects/cjson/files/?source=navbar。同时,要对JSON格式数据进行校验,可以使用在线工具:https://www.bejson.com/进行校验。为了避免其他因素的影响,我没有加入其他与硬件相关的c代码。所以,我必须模拟一个天气数据包来编写测试代码。我把模拟的天气实况天气数据包保存在文本文件now.txt中,如下所示:
二、代码部分
1、结构体定义
为了能更直观,更清晰的表示解析后的天气数据。我定义了三个结构体用于保存解析后得到的天气数据。结构体定义如下:
(1)子对象1结构体--Location
要解析now.txt里的数据,必须先将其读取数来。相关代码语句如下:
解析得到的结果与now.txt中的有用的数据完全一致,解析成功!
三、总结
JSON格式解析的函数中,不必再使用malloc或者之后移植到单片机系统上时也无需再使用自定义的malloc再对arrayItem,object,subobject,item等cJSON型指针变量再申请内存,因为在cJSON_Parse函数内部已经有申请一整块的内存空间供整个解析过程使用,如果再多申请空间,程序在单片机里运行一段时间后可能会导致系统崩溃死机。除此之外,分享一篇让我收益良多的与单片机相关的天气预报系统的例子:http://www.openedv.com/thread-229818-1-1.html。我们都应该有开源共享的精神,互相帮助互相学习才能学得更快更好!
最近做了个基于STM32的天气预报系统。通过wifi模块从心知天气(http://www.seniverse.com/)获取天气数据,其天气数据的格式为JSON格式,对于JSON格式数据的学习,可以参考博文:http://blog.csdn.net/xukai871105/article/details/32346797(这一篇为JSON格式详解)、http://blog.csdn.net/lintax/article/details/50993958(这一篇介绍如何使用cJSON库解析JSON格式数据)和http://blog.csdn.net/taiyang1987912/article/details/49862141(这一篇为cJSON库的介绍)。cJSON库的下载地址为:http://sourceforge.net/projects/cjson/files/?source=navbar。同时,要对JSON格式数据进行校验,可以使用在线工具:https://www.bejson.com/进行校验。为了避免其他因素的影响,我没有加入其他与硬件相关的c代码。所以,我必须模拟一个天气数据包来编写测试代码。我把模拟的天气实况天气数据包保存在文本文件now.txt中,如下所示:
二、代码部分
1、结构体定义
为了能更直观,更清晰的表示解析后的天气数据。我定义了三个结构体用于保存解析后得到的天气数据。结构体定义如下:
(1)子对象1结构体--Location
typedef struct { char id[32]; char name[32]; char country[32]; char path[64]; char timezone[32]; char timezone_offset[32]; }Location;(2)子对象2结构体--Now
typedef struct { char text[32]; char code[32]; char temperature[32]; }Now;(3)用于保存服务器返回的天气数据
typedef struct { Location location; //子对象1 Now now; //子对象2 char last_update[64]; //子对象3 }Results;2、读取now.txt文本文件数据
要解析now.txt里的数据,必须先将其读取数来。相关代码语句如下:
if((fp = fopen("now.txt","rb")) == NULL) { printf("Open error!\n"); return 1; } fseek(fp, 0, SEEK_END); len = ftell(fp); fseek(fp, 0, SEEK_SET); data = (char*)malloc(len+1); fread(data, len, 1, fp); fclose(fp);3、解析JSON格式天气数据
int cJSON_WeatherParse(char *JSON, Results *results) { cJSON *json,*arrayItem,*object,*subobject,*item; json = cJSON_Parse(JSON); //解析JSON数据包 if(json == NULL) //检测JSON数据包是否存在语法上的错误,返回NULL表示数据包无效 { printf("Error before: [%s]\n",cJSON_GetErrorPtr()); //打印数据包语法错误的位置 return 1; } else { if((arrayItem = cJSON_GetObjectItem(json,"results")) != NULL); //匹配字符串"results",获取数组内容 { int size = cJSON_GetArraySize(arrayItem); //获取数组中对象个数 printf("cJSON_GetArraySize: size=%d\n",size); if((object = cJSON_GetArrayItem(arrayItem,0)) != NULL)//获取父对象内容 { /* 匹配子对象1 */ if((subobject = cJSON_GetObjectItem(object,"location")) != NULL) { printf("---------------------------------subobject1-------------------------------\n"); if((item = cJSON_GetObjectItem(subobject,"id")) != NULL) //匹配子对象1成员"id" { printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s\n",item->type,item->string,item->valuestring); memcpy(results[0].location.id,item->valuestring,strlen(item->valuestring)); } if((item = cJSON_GetObjectItem(subobject,"name")) != NULL) //匹配子对象1成员"name" { printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s\n",item->type,item->string,item->valuestring); memcpy(results[0].location.name,item->valuestring,strlen(item->valuestring)); } if((item = cJSON_GetObjectItem(subobject,"country")) != NULL)//匹配子对象1成员"country" { printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s\n",item->type,item->string,item->valuestring); memcpy(results[0].location.country,item->valuestring,strlen(item->valuestring)); } if((item = cJSON_GetObjectItem(subobject,"path")) != NULL) //匹配子对象1成员"path" { printf("cJSON_G bb26 etObjectItem: type=%d, string is %s,valuestring=%s\n",item->type,item->string,item->valuestring); memcpy(results[0].location.path,item->valuestring,strlen(item->valuestring)); } if((item = cJSON_GetObjectItem(subobject,"timezone")) != NULL)//匹配子对象1成员"timezone" { printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s\n",item->type,item->string,item->valuestring); memcpy(results[0].location.timezone,item->valuestring,strlen(item->valuestring)); } if((item = cJSON_GetObjectItem(subobject,"timezone_offset")) != NULL)//匹配子对象1成员"timezone_offset" { printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s\n",item->type,item->string,item->valuestring); memcpy(results[0].location.timezone_offset,item->valuestring,strlen(item->valuestring)); } } /* 匹配子对象2 */ if((subobject = cJSON_GetObjectItem(object,"now")) != NULL) { printf("---------------------------------subobject2-------------------------------\n"); if((item = cJSON_GetObjectItem(subobject,"text")) != NULL)//匹配子对象2成员"text" { printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s\n",item->type,item->string,item->valuestring); memcpy(results[0].now.text,item->valuestring,strlen(item->valuestring)); } if((item = cJSON_GetObjectItem(subobject,"code")) != NULL)//匹配子对象2成员"code" { printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s\n",item->type,item->string,item->valuestring); memcpy(results[0].now.code,item->valuestring,strlen(item->valuestring)); } if((item = cJSON_GetObjectItem(subobject,"temperature")) != NULL) //匹配子对象2成员"temperature" { printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s\n",item->type,item->string,item->valuestring); memcpy(results[0].now.temperature,item->valuestring,strlen(item->valuestring)); } } /* 匹配子对象3 */ if((subobject = cJSON_GetObjectItem(object,"last_update")) != NULL) { printf("---------------------------------subobject3-------------------------------\n"); printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s\n",subobject->type,subobject->string,subobject->valuestring); memcpy(results[0].last_update,item->valuestring,strlen(subobject->valuestring)); } } } } cJSON_Delete(json); //释放cJSON_Parse()分配出来的内存空间 return 0; }4、完整代码
/*----------------------------------------------------------------------------------------该代码的运行结果如下图所示:
Program Explain:解析JSON天气数据包now.json(天气实况)
Create Date:2017.12.6 by lzn
----------------------------------------------------------------------------------------*/
//1、数据来源:心知天气(api.seniverse.com)
//2、获取方法:GET https://api.seniverse.com/v3/weather/now.json?key=2owqvhhd2dd9o9f9&location=beijing&language=zh-Hans&unit=c //3、返回的数据范例见文件now.txt
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "cJSON.h"
//子对象1结构体--Location
typedef struct { char id[32]; char name[32]; char country[32]; char path[64]; char timezone[32]; char timezone_offset[32]; }Location;
//子对象2结构体--Now
typedef struct { char text[32]; char code[32]; char temperature[32]; }Now;
//用于保存服务器返回的天气数据
typedef struct { Location location; //子对象1 Now now; //子对象2 char last_update[64]; //子对象3 }Results;
//函数声明
int cJSON_WeatherParse(char *JSON, Results *results);
/*********************************************************************************
* Function Name : main主函数
* Parameter : NULL
* Return Value : 0
* Function Explain :
* Create Date : 2017.12.6 by lzn
**********************************************************************************/
int main(int argc, char **argv)
{
FILE *fp;
char *data;
int len;
Results results[] = {{0}};
if((fp = fopen("now.txt","rb")) == NULL)
{
printf("Open error!\n");
return 1;
}
fseek(fp, 0, SEEK_END);
len = ftell(fp);
fseek(fp, 0, SEEK_SET);
data = (char*)malloc(len+1);
fread(data, len, 1, fp);
fclose(fp);
printf("read file %s complete, len=%d.\n","now.txt",len);
cJSON_WeatherParse(data, results); //解析天气数据
free(data);
system("pause");
return 0;
}
/*********************************************************************************
* Function Name : cJSON_WeatherParse,解析天气数据
* Parameter : JSON:天气数据包 results:保存解析后得到的有用的数据
* Return Value : 0:成功 其他:错误
* Function Explain :
* Create Date : 2017.12.6 by lzn
**********************************************************************************/
int cJSON_WeatherParse(char *JSON, Results *results)
{
cJSON *json,*arrayItem,*object,*subobject,*item;
json = cJSON_Parse(JSON); //解析JSON数据包
if(json == NULL) //检测JSON数据包是否存在语法上的错误,返回NULL表示数据包无效
{
printf("Error before: [%s]\n",cJSON_GetErrorPtr()); //打印数据包语法错误的位置
return 1;
}
else
{
if((arrayItem = cJSON_GetObjectItem(json,"results")) != NULL); //匹配字符串"results",获取数组内容
{
int size = cJSON_GetArraySize(arrayItem); //获取数组中对象个数
printf("cJSON_GetArraySize: size=%d\n",size);
if((object = cJSON_GetArrayItem(arrayItem,0)) != NULL)//获取父对象内容
{
/* 匹配子对象1 */
if((subobject = cJSON_GetObjectItem(object,"location")) != NULL)
{
printf("---------------------------------subobject1-------------------------------\n");
if((item = cJSON_GetObjectItem(subobject,"id")) != NULL) //匹配子对象1成员"id"
{
printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s\n",item->type,item->string,item->valuestring);
memcpy(results[0].location.id,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"name")) != NULL) //匹配子对象1成员"name"
{
printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s\n",item->type,item->string,item->valuestring);
memcpy(results[0].location.name,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"country")) != NULL)//匹配子对象1成员"country"
{
printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s\n",item->type,item->string,item->valuestring);
memcpy(results[0].location.country,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"path")) != NULL) //匹配子对象1成员"path"
{
printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s\n",item->type,item->string,item->valuestring);
memcpy(results[0].location.path,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"timezone")) != NULL)//匹配子对象1成员"timezone"
{
printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s\n",item->type,item->string,item->valuestring);
memcpy(results[0].location.timezone,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"timezone_offset")) != NULL)//匹配子对象1成员"timezone_offset"
{
printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s\n",item->type,item->string,item->valuestring);
memcpy(results[0].location.timezone_offset,item->valuestring,strlen(item->valuestring));
}
}
/* 匹配子对象2 */
if((subobject = cJSON_GetObjectItem(object,"now")) != NULL)
{
printf("---------------------------------subobject2-------------------------------\n");
if((item = cJSON_GetObjectItem(subobject,"text")) != NULL)//匹配子对象2成员"text"
{
printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s\n",item->type,item->string,item->valuestring);
memcpy(results[0].now.text,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"code")) != NULL)//匹配子对象2成员"code"
{
printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s\n",item->type,item->string,item->valuestring);
memcpy(results[0].now.code,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"temperature")) != NULL) //匹配子对象2成员"temperature"
{
printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s\n",item->type,item->string,item->valuestring);
memcpy(results[0].now.temperature,item->valuestring,strlen(item->valuestring));
}
}
/* 匹配子对象3 */
if((subobject = cJSON_GetObjectItem(object,"last_update")) != NULL)
{
printf("---------------------------------subobject3-------------------------------\n");
printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s\n",subobject->type,subobject->string,subobject->valuestring);
memcpy(results[0].last_update,item->valuestring,strlen(subobject->valuestring));
}
}
}
}
cJSON_Delete(json); //释放cJSON_Parse()分配出来的内存空间
return 0;
}
解析得到的结果与now.txt中的有用的数据完全一致,解析成功!
三、总结
JSON格式解析的函数中,不必再使用malloc或者之后移植到单片机系统上时也无需再使用自定义的malloc再对arrayItem,object,subobject,item等cJSON型指针变量再申请内存,因为在cJSON_Parse函数内部已经有申请一整块的内存空间供整个解析过程使用,如果再多申请空间,程序在单片机里运行一段时间后可能会导致系统崩溃死机。除此之外,分享一篇让我收益良多的与单片机相关的天气预报系统的例子:http://www.openedv.com/thread-229818-1-1.html。我们都应该有开源共享的精神,互相帮助互相学习才能学得更快更好!
相关文章推荐
- 学习笔记——天气数据解析2(JSON格式数据)
- Android阶段学习笔记 7.25-7.29 之 解析聚合数据 全国天气预报 Json
- android 学习笔记 解析json格式的数据 JSONObject 和GSON解析json格式数据
- SpringMVC学习笔记(7) 返回Json格式数据
- Android学习系列(20)--App数据格式之解析Json
- iOS 阶段学习第22天笔记(JSON数据格式介绍)
- Android学习系列(20)--App数据格式之解析Json
- Andorid中使用Gson和Fast-json解析库解析JSON数据---第三方库学习笔记(二)
- iOS学习笔记网络篇之数据解析(JSON/XML)
- android学习二十三(解析json格式数据)
- iphone学习笔记--JSON数据解析
- Cocos2d-x学习笔记(十三)—— 数据解析(json/xml)
- android 学习笔记 Pull 解析XML 格式数据。
- Android 学习笔记之Volley(七)实现Json数据加载和解析...
- iOS学习笔记(十一)——JSON数据解析
- iOS学习笔记(十一)——JSON数据解析
- jQuery学习笔记--ajax查询,jQuery解析返回的json数据 详解
- javascript学习笔记(六)数据类型和JSON格式
- jQuery学习笔记--ajax查询,jQuery解析返回的json数据 详解
- Android学习系列(20)--App数据格式之解析Json