Linux-C C语言使用cJSON开源库解析JSON数据
一、简述
记--在C语言中使用cJSON开源库解析JSON数据。
例子1:读取简单的JSON数据
例子2:读取JSON数据文件
例子3:读取JSON对象嵌套数据
例子4:读取JSON数组数据
二、例子
cJSON第三方解析库:cJSON_x86.tar.gz
链接: https://pan.baidu.com/s/1jFhRZ8RDpMftlMKZU5M8_g 提取码: s7ib
解压:tar -xjvf cJSON_x86.tar.bz2 //将cJSON_x86.tar.bz2解压到当前路径
例子1:读取简单的JSON数据
#include <stdio.h>
#include <stdlib.hs>
#include "cJSON.h"
int main(int argc, char* argv[])
{
char buf[1024] = {" {\"date\":\"20181128\"} "};//要解析的json数据
cJSON * root = cJSON_Parse(buf);//将字符串格式的json数据转化为JSON对象格式
if(root == NULL)
{
printf("parse error\n");
return -1;
}
cJSON *value = cJSON_GetObjectItem(root, "date");//根据键"date"获取其对应的值
if(value == NULL)
{
printf("getvalue error\n");
cJSON_Delete(root);
return -1;
}
char *data = cJSON_Print(value);//将获取值转化为字符串格式
if(data == NULL)
{
printf("printf error\n");
cJSON_Delete(root);
return -1;
}
printf("data=%s\n", data);//打印获取到的json数据
free(data);
//释放资源
cJSON_Delete(root); //json对象释放根节点,会自动释放子节点
return 0;
}
效果:编译命令:gcc json.c -o json -I ~/cJSON/include/cjson/ -L ~/cJSON/lib -lcjson
注:需要将cjson.so库放到环境变量:export LD_LIBRARY_PATH=/home/liang/cJSON/lib:$LD_LIBRARY_PATH
例子2:读取JSON数据文件
data.json 数据文件
{
"date": "29日星期四",
"sunrise": "07:08",
"high": "高温 9.0℃",
"low": "低温 0.0℃",
"sunset": "16:50",
"aqi": 50.0,
"fx": "东风",
"fl": "4-5级",
"type": "晴",
"notice": "愿你拥有比阳光明媚的心情"
}
测试代码:
#include <stdio.h>
#include "cJSON.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
//打开JSON数据文件
int fd = open("data.json",O_RDWR);
if(fd < 0)
{
perror("open fail\n");
return -1;
}
//读取文件中的数据
char buf[2048]={0};
int ret = read(fd, buf, sizeof(buf));
if(ret == -1)
{
perror("read error");
return -1;
}
//关闭文件
close(fd);
//把该字符串数据转换成JSON对象
cJSON *root=cJSON_Parse(buf);
if(root == NULL)
{
printf("parse error\n");
return -1;
}
//根据key值去获取对应的value
cJSON *value = cJSON_GetObjectItem(root,"date");
if(value == NULL)
{
printf("GetObjec error\n");
return -1;
}
//把数据转成 字符串输出
char *data = cJSON_Print(value);
printf("date=%s\n",data);
free(data);
data = NULL;
value = cJSON_GetObjectItem(root,"fx");
if(value == NULL)
{
printf("GetObjec error\n");
cJSON_Delete(root);
return -1;
}
//把数据转成 字符串输出
data = cJSON_Print(value);
printf("notice=%s\n",data);
free(data);
data = NULL;
//根据key值去获取对应的value
value = cJSON_GetObjectItem(root,"notice");
if(value == NULL)
{
printf("GetObjec error\n");
cJSON_Delete(root);
return -1;
}
//把数据转成 字符串输出
data = cJSON_Print(value);
printf("notice=%s\n",data);
free(data);
data = NULL;
//释放资源
cJSON_Delete(root); //json对象释放根节点,会自动释放子节点
return 0;
}
效果:
例子3:读取JSON对象嵌套数据,获取键"quality"和键"notice"对应的数据。
JSON数据:
{
"status": 200,
"data": {
"shidu": "35%",
"pm25": 55.0,
"pm10": 177.0,
"quality": "轻度污染",
"wendu": "4",
"ganmao": "儿童、老年人及心脏、呼吸系统疾病患者人群应减少长时间或高强度户外锻炼",
"yesterday": {
"date": "27日星期二",
"sunrise": "07:06",
"high": "高温 10.0℃",
"low": "低温 0.0℃",
"sunset": "16:51",
"aqi": 253.0,
"fx": "南风",
"fl": "<3级",
"type": "晴",
"notice": "愿你拥有比阳光明媚的心情"
}
}
}
代码:
#include <stdio.h>
#include "cJSON.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
//打开保存JSON数据的文件
int fd = open("data.json",O_RDWR);
if(fd < 0)
{
perror("open fail\n");
return -1;
}
//读取文件中的数据
char buf[2048]={0};
int ret = read(fd, buf, sizeof(buf));
if(ret == -1)
{
perror("read error");
return -1;
}
//关闭文件
close(fd);
//把该字符串数据转换成JSON数据 (对象)
cJSON *root=cJSON_Parse(buf);
if(root == NULL)
{
printf("parse error\n");
return -1;
}
//取该对象中的value值
cJSON *value = cJSON_GetObjectItem(root,"data");//获取键"data"对应的JSON值
if(value == NULL)
{
printf("GetObjec error\n");
cJSON_Delete(root);
return -1;
}
cJSON *value2 = cJSON_GetObjectItem(value,"quality");//获取键"quality"对应的JSON值
char *data = cJSON_Print(value2);
printf("quality=%s\n", data);
free(data);
data = NULL;
value = cJSON_GetObjectItem(value,"yesterday");//获取键"yesterday"对应的JSON值
if(value == NULL)
{
printf("GetObjec error\n");
cJSON_Delete(root);
return -1;
}
value = cJSON_GetObjectItem(value,"notice"); //获取键"notice"对应的JSON值
data = cJSON_Print(value);
printf("notice=%s\n", data);
free(data);
data = NULL;
//释放资源
cJSON_Delete(root);
return 0;
}
效果:
例子4:读取JSON数组数据
JSON数据:
{
"time": "2018-11-28 09:06:12",
"forecast": [{
"date": "28日星期三",
"sunrise": "07:07",
"high": "高温 11.0℃",
"low": "低温 1.0℃",
"sunset": "16:50",
"aqi": 116.0,
"fx": "东风",
"fl": "<3级",
"type": "多云",
"notice": "阴晴之间,谨防紫外线侵扰"
}, {
"date": "29日星期四",
"sunrise": "07:08",
"high": "高温 9.0℃",
"low": "低温 0.0℃",
"sunset": "16:50",
"aqi": 50.0,
"fx": "东风",
"fl": "4-5级",
"type": "晴",
"notice": "愿你拥有比阳光明媚的心情"
}, {
"date": "30日星期五",
"sunrise": "07:09",
"high": "高温 11.0℃",
"low": "低温 0.0℃",
"sunset": "16:50",
"aqi": 89.0,
"fx": "西风",
"fl": "3-4级",
"type": "晴",
"notice": "愿你拥有比阳光明媚的心情2"
}, {
"date": "01日星期六",
"sunrise": "07:10",
"high": "高温 12.0℃",
"low": "低温 3.0℃",
"sunset": "16:49",
"aqi": 106.0,
"fx": "东南风",
"fl": "<3级",
"type": "晴",
"notice": "愿你拥有比阳光明媚的心情3"
}, {
"date": "02日星期日",
"sunrise": "07:11",
"high": "高温 10.0℃",
"low": "低温 2.0℃",
"sunset": "16:49",
"aqi": 174.0,
"fx": "南风",
"fl": "3-4级",
"type": "阴",
"notice": "不要被阴云遮挡住好心情"
}]
}
测试代码:
#include <stdio.h>
#include "cJSON.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
//打开保存JSON数据的文件
int fd = open("data.json",O_RDWR);
if(fd < 0)
{
perror("open fail\n");
return -1;
}
//读取文件中的数据
char buf[2048] = {0};
int ret = read(fd, buf, sizeof(buf));
if(ret == -1)
{
perror("read error");
return -1;
}
//关闭文件
close(fd);
//把该字符串数据转换成JSON数据 (对象)
cJSON *root=cJSON_Parse(buf);
if(root == NULL)
{
printf("parse error\n");
return -1;
}
//根据key值去获取对应的value
cJSON *value = cJSON_GetObjectItem(root,"time");
if(value == NULL)
{
printf("GetObjectItem error\n");
cJSON_Delete(root);
return -1;
}
//把数据转成 字符串输出
char* data = cJSON_Print(value);
printf("time=%s\n",data);
free(data);
data = NULL;
//获取数组对象
//当前的value 是一个数组对象
value = cJSON_GetObjectItem(root,"forecast");
if(value == NULL)
{
printf("GetObjectItem error\n");
cJSON_Delete(root);
return -1;
}
//获取该数组对象的大小
int len = cJSON_GetArraySize(value);
printf("元素个数len=%d\n",len);
//根据下标获取对象 取出第0项
int i = 0;
char* val = NULL;
cJSON * type_value = NULL;
cJSON * date_value = NULL;
for(i=0;i<len;i++)
{
date_value = cJSON_GetArrayItem(value,i);
type_value = cJSON_GetArrayItem(value,i);
//获取KEY对应的value
date_value = cJSON_GetObjectItem(date_value,"date");
type_value = cJSON_GetObjectItem(type_value,"type");
if(date_value == NULL || type_value == NULL)
{
printf("GetObjectItem error\n");
cJSON_Delete(root);
return -1;
}
//获取完毕后转换打印
data = cJSON_Print(date_value);
val = cJSON_Print(type_value);
printf("%s\t%s\n", data, val);
free(data);
free(val);
}
cJSON_Delete(root);
return -1;
}
效果:
三、总结
3.1 使用完JSON对象后需要释放,释放跟节点即可。
//json对象释放根节点,会自动释放子节点
cJSON * root = cJSON_Parse(buf);
cJSON_Delete(root);
3.2 cJSON_Print(), print_number(), parse_string()返回值非空时是一个堆空间地址,使用完需要释放, 一个cJSON_Print对应一个free。
cJSON *json;
json = cJSON_Parse(buf);
if (NULL != json) {
char *out = cJSON_Print(json);
if (NULL != out) {
printf("%s\n",out);
free(out);
}
cJSON_Delete(json);
}
例如:结果是数字类型
cJSON_Print() --》print_value() --》print_number() --》cJSON_malloc() --》malloc()