cjson 对象是json数组型结构体_一款轻量级的JSON解析库,用cJSON让你看清王者荣耀...

2021年的第一篇文章,带你看清王者荣耀知乎视频​www.zhihu.com

完整代码:

提取码:18re

JSON是一种轻量级的数据格式,应用广泛。在C/C++应用中也常常作为配置文件或者数据的存储

JSON语法规则

JSON对象是一个无序的"名称/值"键值对的集合:以"{“开始,以”}"结束,允许嵌套使用;

每个名称和值成对出现,名称和值之间使用":"分隔;

键值对之间用","分隔

在这些字符前后允许存在无意义的空白符;

对于键值,可以有如下值:一个新的json对象

数组:使用"[“和”]"表示

数字:直接表示,可以是整数,也可以是浮点数

字符串:使用引号"表示

字面值:false、null、true中的一个(必须是小写)

示例如下:

[{

"ename": 105,

"cname": "廉颇",

"title": "正义爆轰",

"new_type": 0,

"hero_type": 3,

"skin_name": "正义爆轰|地狱岩魂"

}, {

"ename": 106,

"cname": "小乔",

"title": "恋之微风",

"new_type": 0,

"hero_type": 2,

"skin_name": "恋之微风|万圣前夜|天鹅之梦|纯白花嫁|缤纷独角兽"

}]

cJSON

cJSON下载使用

cJSON是使用ANSI C编写的超轻量级的JSON解析器,因此在C中也常常是不二之选。

cJSON项目托管在Github上,仓库地址如下:

使用Git命令将其拉取到本地:

git clone https://github.com/DaveGamble/cJSON.git

从Github拉取cJSON源码后,文件非常多,但是其中cJSON的源码文件只有两个:cJSON.h

cJSON.c

使用的时候,只需要将这两个文件复制到工程目录,然后包含头文件cJSON.h即可,如下:

#include "cJSON.h"

关键数据结构

cJSON的关键数据结构如下:

typedef struct cJSON { //cJSON结构体 struct cJSON*next,*prev; /*后驱节点和前驱节点*/

struct cJSON *child; /*孩子节点*/

int type; /* 键的类型*/

char *valuestring; /*字符串值*/

int valueint; /* 整数值*/

double valuedouble; /* 浮点数值*/

char *string; /* 键的名字*/

} cJSON;

json是一种组织良好的数据格式,因而JSON中的内容解析后,都可以通过以上数据结构进行处理。

例如,对于下面的json内容:

{

"name":"编程学习基地",

"site":"https://www.deroy.cn",

"age":1

}

解析后,site将会是name的next节点,并且它的键类型是字符串。

cJSON数据解析

常用接口函数

用于将字符串解析成json对象,若失败则返回NULL。

cJSON *cJSON_Parse(const char *value);

用于获取json对象中的某个节点,若失败,返回NULL,成功则返回该节点对象。

cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);

用于释放json对象相关内存。

void cJSON_Delete(cJSON *c);

如果JSON数据的值是数组,可以通过下面接口获取 JSON 数组大小和数组里面的 JSON 对象

int cJSON_GetArraySize(const cJSON *array);

cJSON * cJSON_GetArrayItem(const cJSON *array, int index);

解析步骤将JSON文件内容读取到buffer

通过cJSON接口解析buffer中的字符串

获取JSON指定字段

为了将JSON文件的内容读取到buffer,需要知道文件的大小:

size_t get_file_size(const char *filepath)

{

/*check input para*/

if(NULL == filepath)

return 0;

struct stat filestat;

memset(&filestat,0,sizeof(struct stat));

/*get file information*/

if(0 == stat(filepath,&filestat))

return filestat.st_size;

else

return 0;

}

然后申请一段内存,将文件中的文本读取到buffer中:

char *read_file_to_buf(const char *filepath)

{

/*check input para*/

if(NULL == filepath)

{

return NULL;

}

/*get file size*/

size_t size = get_file_size(filepath);

if(0 == size)

return NULL;

/*malloc memory*/

char *buf = malloc(size+1);

if(NULL == buf)

return NULL;

memset(buf,0,size+1);

/*read string from file*/

FILE *fp = fopen(filepath,"r");

size_t readSize = fread(buf,1,size,fp);

if(readSize != size)

{

/*read error*/

free(buf);

buf = NULL;

}

buf[size] = 0;

return buf;

}

再根据前面提到的解析流程,我们的JSON预解析函数如下:

cJSON *prepare_parse_json(const char *filePath)

{

/*check input para*/

if(NULL == filePath)

{

printf("input para is NULL\n");

return NULL;

}

/*read file content to buffer*/

char *buf = read_file_to_buf(filePath);

if(NULL == buf)

{

printf("read file to buf failed\n");

return NULL;

}

/*parse JSON*/

cJSON *pTemp = cJSON_Parse(buf);

free(buf);

buf = NULL;

return pTemp;

}

解析示例

#include#include#include#include#include"cJSON.h"

size_t get_file_size(const char *filepath)

{

/*check input para*/

if(NULL == filepath)

return 0;

struct stat filestat;

memset(&filestat,0,sizeof(struct stat));

/*get file information*/

if(0 == stat(filepath,&filestat))

return filestat.st_size;

else

return 0;

}

char *read_file_to_buf(const char *filepath)

{

/*check input para*/

if(NULL == filepath)

{

return NULL;

}

/*get file size*/

size_t size = get_file_size(filepath);

if(0 == size)

return NULL;

/*malloc memory*/

char *buf = malloc(size+1);

if(NULL == buf)

return NULL;

memset(buf,0,size+1);

/*read string from file*/

FILE *fp = fopen(filepath,"r");

size_t readSize = fread(buf,1,size,fp);

if(readSize != size)

{

/*read error*/

free(buf);

buf = NULL;

}

buf[size] = 0;

return buf;

}

/**/

cJSON *prepare_parse_json(const char *filePath)

{

/*check input para*/

if(NULL == filePath)

{

printf("input para is NULL\n");

return NULL;

}

/*read file content to buffer*/

char *buf = read_file_to_buf(filePath);

if(NULL == buf)

{

printf("read file to buf failed\n");

return NULL;

}

/*parse JSON*/

cJSON *pTemp = cJSON_Parse(buf);

free(buf);

buf = NULL;

return pTemp;

}

int main(void)

{

char *filename = "herolist.json";

cJSON *pJson = NULL;

cJSON *pTemp = NULL;

cJSON *pVal = NULL;

/*创建cJSON对象*/

pJson = prepare_parse_json(filename);

if(NULL == pJson)

{

printf("parse json failed\n");

return -1;

}

/*获取cJSON数组数量*/

int num = cJSON_GetArraySize(pJson);

/*遍历每一个cJSON数组元素*/

for(int index=0;index

{

/*获取cJSON数组中的第index个cJSON对象*/

pTemp = cJSON_GetArrayItem(pJson,index);

/*获取cJSON对象中的key值为ename的对象*/

pVal = cJSON_GetObjectItem(pTemp,"ename");

printf("ename:%d\n",pVal->valueint);

pVal = cJSON_GetObjectItem(pTemp,"cname");

printf("cname:%s\n",pVal->valuestring);

pVal = cJSON_GetObjectItem(pTemp,"title");

printf("title:%s\n",pVal->valuestring);

pVal = cJSON_GetObjectItem(pTemp,"new_type");

printf("new_type:%d\n",pVal->valueint);

pVal = cJSON_GetObjectItem(pTemp,"hero_type");

printf("hero_type:%d\n",pVal->valueint);

pVal = cJSON_GetObjectItem(pTemp,"skin_name");

printf("skin_name:%s\n\n",pVal->valuestring);

printf("====================================\n\n");

}

/*释放内存*/

cJSON_Delete(pJson);

pJson = NULL;

return 0;

}

gcc -o mian main.c cJSON.c

windows下VC6.0,VS也可以运行,但是因为编码格式问题,我另写了一套程序

为了让输出看起来舒服,改了点格式,输出如下(删减),源码获取发送关键字【王者荣耀】

|ename|cname|title|new_type|hero_type|skin_name|

-----------------------------------------------------------------------------------------------------------

|105|廉颇|正义爆轰|0|3|正义爆轰|地狱岩魂|

-----------------------------------------------------------------------------------------------------------

|106|小乔|恋之微风|0|2|恋之微风|万圣前夜|天鹅之梦|纯白花嫁|缤纷独角兽|

-----------------------------------------------------------------------------------------------------------

|107|赵云|苍天翔龙|0|1|苍天翔龙|忍●炎影|未来纪元|皇家上将|嘻哈天王|白执事|引擎之心|

-----------------------------------------------------------------------------------------------------------

|108|墨子|和平守望|0|2|和平守望|金属风暴|龙骑士|进击墨子号|

-----------------------------------------------------------------------------------------------------------

JSON数据封装

封装方法

封装JSON数据的过程,其实就是创建链表和向链表中添加节点的过程。

首先来讲述一下链表中的一些术语:头指针:指向链表头结点的指针;

头结点:不存放有效数据,方便链表操作;

首节点:第一个存放有效数据的节点;

尾节点:最后一个存放有效数据的节点;

封装步骤

明白了这几个概念之后,我们开始讲述创建一段完整的JSON数据,即如何创建一条完整的链表。① 创建头指针:

cJSON* cjson_test = NULL;② 创建头结点,并将头指针指向头结点:

cjson_test = cJSON_CreateObject();③ 尽情的向链表中添加节点:

/* 添加一个值为 null 的布尔类型的JSON数据(添加一个链表节点) */

cJSON_AddNullToObject(cJSON * const object, const char * const name);

/* 添加一个值为 true 的布尔类型的JSON数据(添加一个链表节点) */

cJSON_AddTrueToObject(cJSON * const object, const char * const name);

/* 添加一个值为 False 的布尔类型的JSON数据(添加一个链表节点) */

cJSON_AddFalseToObject(cJSON * const object, const char * const name);

/* 添加一个值为布尔类型的JSON数据 0:false 非0:true (添加一个链表节点) */

cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);

/* 添加一条数值类型的JSON数据(添加一个链表节点) */

cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);

/* 添加一条字符串类型的JSON数据(添加一个链表节点) */

cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);

/* 添加一行数据(添加一个链表节点) */

cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);

/* 添加一个空对象(添加一个链表节点) */

cJSON_AddObjectToObject(cJSON * const object, const char * const name);

/* 添加一个空数组(添加一个链表节点) */

cJSON_AddArrayToObject(cJSON * const object, const char * const name);

/* 添加一个嵌套的JSON对象/数组(添加一个链表节点) */

cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);

cJSON还提供了将JSON对象转换成字符串输出到终端

char *cJSON_Print(const cJSON *item);

封装示例

#include #include "cJSON.h"int main(void)

{

cJSON* cjson_test = NULL;

cJSON* cjson_address = NULL;

cJSON* cjson_skill = NULL;

char* str = NULL;

/* 创建一个JSON数据对象(链表头结点) */

cjson_test = cJSON_CreateObject();

/* 添加一个值为 null 的布尔类型的JSON数据(添加一个链表节点) */

cJSON_AddNullToObject(cjson_test, "null_test");

/* 添加一个值为 true 的布尔类型的JSON数据(添加一个链表节点) */

cJSON_AddTrueToObject(cjson_test,"true_test");

/* 添加一个值为 False 的布尔类型的JSON数据(添加一个链表节点) */

cJSON_AddFalseToObject(cjson_test, "false_test");

/* 添加一个值为布尔类型的JSON数据 0:false 非0:true (添加一个链表节点) */

cJSON_AddBoolToObject(cjson_test, "bool_test", 0);

/* 添加一条整数类型的JSON数据(添加一个链表节点) */

cJSON_AddNumberToObject(cjson_test, "int_test", 22);

/* 添加一条浮点类型的JSON数据(添加一个链表节点) */

cJSON_AddNumberToObject(cjson_test, "double_test", 55.5);

/* 添加一条字符串类型的JSON数据(添加一个链表节点) */

cJSON_AddStringToObject(cjson_test, "str_test", "我是字符串");

/* 添加一行任意数据(添加一个链表节点) */

cJSON_AddRawToObject(cjson_test, "key", "任意数据");

/* 添加一个空对象(添加一个链表节点) */

cJSON_AddObjectToObject(cjson_test, "objet");

/* 添加一个嵌套的JSON对象(添加一个链表节点) */

cjson_address = cJSON_CreateObject();

cJSON_AddStringToObject(cjson_address, "country", "China");

cJSON_AddNumberToObject(cjson_address, "zip-code", 111111);

cJSON_AddItemToObject(cjson_test, "address", cjson_address);

/* 添加一个空数组(添加一个链表节点) */

cJSON_AddArrayToObject(cjson_test, "Array");

/* 添加一个数组类型的JSON数据(添加一个链表节点) */

cjson_skill = cJSON_CreateArray();

cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "C" ));

cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "C++" ));

cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "Python" ));

cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "Java"));

cJSON_AddItemToObject(cjson_test, "skill", cjson_skill);

/* 打印JSON对象(整条链表)的所有数据 */

str = cJSON_Print(cjson_test);

printf("%s\n", str);

return 0;

}

输出结果:

{

"null_test":null,

"true_test":true,

"false_test":false,

"bool_test":false,

"int_test":22,

"double_test":55.5,

"str_test":"我是字符串",

"key":任意数据,

"objet":{

},

"address":{

"country":"China",

"zip-code":111111

},

"Array":[],

"skill":["C", "C++", "Python", "Java"]

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值