前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一个超轻量级的JSON解析器

一个超轻量级的JSON解析器

作者头像
编程珠玑
发布2019-08-06 17:41:14
1.7K0
发布2019-08-06 17:41:14
举报
文章被收录于专栏:编程珠玑编程珠玑

前言

众所周知,JSON是一种轻量级的数据格式,应用广泛。在C/C++应用中也常常作为配置文件或者数据的存储,因此JSON文件的生成和解析是必备知识。

cJSON

cJSON是使用ANSI C编写的超轻量级的JSON解析器,因此在C中也常常是不二之选。 github 地址:https://github.com/DaveGamble/cJSON

下载到本地后,进行编译:

代码语言:javascript
复制
$ make

执行完成后即可在当前目录下得到libcjson.a和libcjson.so。

当然你也可以只下载cJSON.c和cJSON.h自己编译成静态库或动态库,可参考前期文章《如何制作静态库》和《动态库的制作和两种使用方式》。编译后的.a保留调试信息也只有不过43k。

关键数据结构

cJSON的关键数据结构如下:

代码语言:javascript
复制
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内容:

代码语言:javascript
复制
{
    "name":"编程珠玑",
    "site":"https://www.yanbinghu.com",
    "age":
}

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

常用接口函数

代码语言:javascript
复制
cJSON *cJSON_Parse(const char *value);

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

代码语言:javascript
复制
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);

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

代码语言:javascript
复制
void   cJSON_Delete(cJSON *c);

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

代码语言:javascript
复制
char *cJSON_Print(const cJSON *item);

用于将JSON对象转换成字符串,记得最后释放相关内存。

JSON文件解析准备

解析JSON文件可大致分为以下几个步骤:

  • 获取文件大小
  • 将JSON文件内容读取到buffer
  • 通过cJSON接口解析buffer中的字符串
  • 获取JSON指定字段

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

代码语言:javascript
复制
//来源:公众号【编程珠玑】
//https://www.yanbinghu.com
size_t get_file_size(const char *filepath)
{
    /*check input para*/
    if(NULL == filepath)
        return ;
    struct stat filestat;
    memset(&filestat,,sizeof(struct stat));
    /*get file information*/
    if( == stat(filepath,&filestat))
        return filestat.st_size;
    else
        return ;
}

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

代码语言:javascript
复制
//来源:公众号【编程珠玑】
//https://www.yanbinghu.com
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( == size)
        return NULL;

    /*malloc memory*/
    char *buf = malloc(size+);
    if(NULL == buf)
        return NULL;
    memset(buf,,size+);

    /*read string from file*/
    FILE *fp = fopen(filepath,"r");
    size_t readSize = fread(buf,,size,fp);
    if(readSize != size)
    {
        /*read error*/
        free(buf);
        buf = NULL;
    }

    buf[size] = ;
    return buf;
}

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

代码语言:javascript
复制
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;
}

来源:公众号【编程珠玑】 网站:https://www.yanbinghu.com

解析JSON文件

假设我们的JSON文件内容如下:

代码语言:javascript
复制
{
    "name":"编程珠玑",
    "site":"https://www.yanbinghu.com",
    "age":
}

按照我们前面梳理的解析JSON的步骤,main函数代码如下:

代码语言:javascript
复制
int main(void)
{
    char *filename = "./test.json";
    cJSON *pJson = NULL;
    cJSON *pTemp = NULL;
    pJson = prepare_parse_json(filename);
    if(NULL == pJson)
    {
        printf("parse json failed\n");
        return -1;
    }
    /*获取name值*/
    pTemp = cJSON_GetObjectItem(pJson,"name");
    printf("name is %s\n",pTemp->valuestring);
    /*获取site值*/
    pTemp = cJSON_GetObjectItem(pJson,"site");
    printf("site is %s\n",pTemp->valuestring);

    /*获取age值*/
    pTemp = cJSON_GetObjectItem(pJson,"age");
    printf("age is %d\n",pTemp->valueint);
    /*记得释放相关内存*/
    cJSON_Delete(pJson);
    pJson = NULL;
    return ;
}

从上面看来,我们自己封装好之后,解析json似乎也没有那么复杂? 编译:

代码语言:javascript
复制
$ gcc -L .  -o parseJson parseJson.c -lcjson

注意指定链接cjson库的路径。

运行:

代码语言:javascript
复制
$ ./parseJson
name is 编程珠玑
site is https://www.yanbinghu.com
age is 

写JSON

写JSON又该如何呢?实际上不过是组装JSON对象罢了。示例代码如下:

代码语言:javascript
复制
#include<stdio.h>
#include<stdlib.h>
#include"cJSON.h"
int main(void)
{
    cJSON *pRoot = NULL;
    char *json = NULL;
    cJSON *array = NULL;
    //创建根节点对象
    pRoot = cJSON_CreateObject();
    //向根节点加入数字对象
    cJSON_AddNumberToObject(pRoot, "age", );
    //向根节点加入字符串对象
    cJSON_AddStringToObject(pRoot, "name", "编程珠玑");
    //创建数组对象
    array = cJSON_CreateArray();
    cJSON_AddStringToObject(array,"language","C");
    cJSON_AddStringToObject(array,"language","C++");
    //向根节点中添加数组
    cJSON_AddItemToObject(pRoot,"array",array);
    //解析成字符串
    json = cJSON_Print(pRoot);
    printf("%s\n", json);//这里也可以将字符串写入文件
    //释放json对象的空间
    cJSON_Delete(pRoot);
    pRoot = NULL;
    //记得释放json的空间
    free(json);
    json = NULL;
    return ;
}

运行结果:

代码语言:javascript
复制
{
    "age":  ,
    "name": "编程珠玑",
    "array":    ["C", "C++"]
}

总结

相比于python一条搞定解析来说,C语言中解析JSON似乎显得有些麻烦,但cJSON无疑是一个超轻量级的JSON器。

本文完整代码和点击阅读原文或者访问 http://www.yanbinghu.com/2019/08/04/21364.html 查看附录部分。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程珠玑 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • cJSON
  • 关键数据结构
  • 常用接口函数
  • JSON文件解析准备
  • 解析JSON文件
  • 写JSON
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档