c#读取json某一节点数据_一款轻量级的JSON解析库,用cJSON让你看清王者荣耀

点击蓝字 关注我们

前言

王者荣耀出新英雄了,蔡文姬也迎来了属于她的澜朋友,那么本期带你揭秘王者全英雄全皮肤,一起来看看吧~  0b826dfcb965fb0460bb5fd6b43433dd.png

正文

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上,仓库地址如下:

https://github.com/DaveGamble/cJSON

使用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 = (char*)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下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"]
}

关键字【王者荣耀】

--End--


作者:梦凡 梦想在,终不凡~ 你们的在看就是对我最大的肯定, 点个在看好吗~
3fe1d6879dfc035899e75c9abcbd0afc.png
编程学习基地 常回基地看看
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值