Linux C/C++下使用cJSON解析文件

前言

在工作中遇到用cJSON用来配置文件或者数据存储。今天写一篇博客来记录一下cJSON基础使用。

cJSON简介

JSON(JavaScriptObject Notation)是一种轻量级的数据交换格式。它基于JavaScript的一个子集。JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯。这些特性使JSON成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成。

为何选择cJSON

cJSON是一个超轻巧,携带方便,单文件,简单的可以作为ANSI-C标准的JSON解析器。

github 地址:

https://github.com/DaveGamble/cJSON

下载完后,解压从里面找到两个文件(cJSON.c、cJSON.h),复制到工程里面。只需在函数中包含头文件(#include “cJSON.h”),然后和cJSON.c一起编译即可使用。

Linux 下编译方式:

gcc cJSON.c test.c -o jsontest  -lm  

cJSON的核心结构体

cJSON的核心结构体就是一个cJSON,其结构如下:

扫描二维码关注公众号,回复: 8942295 查看本文章
typedef struct cJSON {
       struct cJSON*next,*prev;           /* 遍历数组或对象链的前向或后向链表指针*/
       struct cJSON *child;                   /*数组或对象的孩子节点*/
       int type;                                     /* 键的类型*/
       char *valuestring;                       /*字符串值*/
       int valueint;                                /* 整数值*/
       double valuedouble;                    /* 浮点数值*/
       char *string;                               /* 键的名字*/
} cJSON;

cJSON是用双链表写的,通过next / prev指针来查找。每个节点也可以有孩子节点,通过child指针来访问。

常用接口函数

CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);

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

CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);

释放cJSON_Parse()分配出来的内存空间。

CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);

返回数组中的项数

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

调用cJSON_GetObjectItem()函数,可从cJSON结构体中查找某个子节点名称(键名称),如果查找成功可把该子节点序列化到cJSON结构体中。

CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);

将cJSON实体呈现为用于传输/存储的文本。

解析JSON格式

要想解析JSON格式,首先需要实现读文件的功能,然后开始JSON字符串的解析。解析文件可以大致分为以下几步骤:

1、在Linux上想要获取文件大小,可以选用stat函数获取文件大小信息
2、申请一段内存,将文件中的文本读取到buffer中
3、通过cJSON_Parse接口解析buffer中的字符串
4、用cJSON_GetObjectItem 接口解析获取指定字段

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

test.json

{
"people":[
{"firstName":"minger","lastName":"minger","email":"[email protected]","age":23,"height":1.67},
{"firstName":"jinmeng","lastName":"meng","email":"[email protected]","age":18,"height":1.177},
{"email":"[email protected]","firstName":"chen","lastName":"jun","age":26,"height":1.75}
]
} 

test_cJSON.c 实现了结构体数组的解析

#include <stdio.h> 
#include <string.h> 
#include <sys/types.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include<sys/stat.h>  //stat
#include "cJSON.h" 
#define   FILENAME  "./test.json"

typedef struct 
{  
     int id;  
     char firstName[32];  
     char lastName[32];  
     char email[64];  
     int age;  
     float height;  
}people;  
 

//解析一个结构数组 
int cJSON_to_struct_array(char *text, people worker[])  
{  
    cJSON *json,*arrayItem,*item,*object;  
    int i = 0;  
 
    json=cJSON_Parse(text);  
    if (!json)  
    {  
        printf("Error before: [%s]\n",cJSON_GetErrorPtr());  
    }  
    else 
    {  
        arrayItem=cJSON_GetObjectItem(json,"people");  // 获取json对象中的people节点
        if(arrayItem!=NULL)  
        {  
            int size=cJSON_GetArraySize(arrayItem);  //获取数组大小
            printf("cJSON_GetArraySize: size=%d\n",size);  
 
            for(i=0;i<size;i++)  
            {  
                printf("i=%d\n",i);  
                object=cJSON_GetArrayItem(arrayItem,i);  
 
                item=cJSON_GetObjectItem(object,"firstName"); // 获取json对象中的firstName节点
                if(item!=NULL)  
                {  
                    printf("cJSON_GetObjectItem: type=%d, string is %s\n",item->type,item->string);  
                    memcpy(worker[i].firstName,item->valuestring,strlen(item->valuestring));  
                }  
 
                item=cJSON_GetObjectItem(object,"lastName");  
                if(item!=NULL)  
                {  
                    printf("cJSON_GetObjectItem: type=%d, string is %s, valuestring=%s\n",item->type,item->string,item->valuestring);  
                    memcpy(worker[i].lastName,item->valuestring,strlen(item->valuestring));  
                }  
 
                item=cJSON_GetObjectItem(object,"email");  
                if(item!=NULL)  
                {  
                    printf("cJSON_GetObjectItem: type=%d, string is %s, valuestring=%s\n",item->type,item->string,item->valuestring);  
                    memcpy(worker[i].email,item->valuestring,strlen(item->valuestring));  
                }  
 
                item=cJSON_GetObjectItem(object,"age");  
                if(item!=NULL)  
                {  
                    printf("cJSON_GetObjectItem: type=%d, string is %s, valueint=%d\n",item->type,item->string,item->valueint);  
                    worker[i].age=item->valueint;  
                }  
                else 
                {  
                    printf("cJSON_GetObjectItem: get age failed\n");  
                }  
 
                item=cJSON_GetObjectItem(object,"height");  
                if(item!=NULL)  
                {  
                    printf("cJSON_GetObjectItem: type=%d, string is %s, value=%f\n",item->type,item->string,item->valuedouble);  
                    worker[i].height=item->valuedouble;  
                }  
            }  
        }  
  
    printf("\n\n");
        for(i=0;i<3;i++)  
        {  
            printf("i=%d, firstName=%s,lastName=%s,email=%s,age=%d,height=%f\n",  
                    i,  
                    worker[i].firstName,  
                    worker[i].lastName,  
                    worker[i].email,  
                    worker[i].age,  
                    worker[i].height);  
        }  
 
        cJSON_Delete(json);  
    }  
    return 0;  
}  
 
size_t get_file_size(const char *filepath)
{
   
    if(NULL == filepath)
        return 0;
    struct stat filestat;
    memset(&filestat,0,sizeof(struct stat));
    /*获取文件信息*/
    if(0 == stat(filepath,&filestat))
        return filestat.st_size;
    else
        return 0;
}


void read_file(char *filename)  
{  
     FILE *fp;  

     people worker[3]={{0}};  

  /*get file size*/
    size_t size = get_file_size(filename);
    if(0 == size)
    {
        printf("get_file_size failed!!!\n");
    }
        
    /*malloc memory*/
    char *buf = malloc(size+1);
    if(NULL == buf)
    {
        printf("malloc failed!!!\n");
        
    }
    memset(buf,0,size+1);

    fp=fopen(filename,"rb");  

    fread(buf,1,size,fp);  
    fclose(fp);  
 
    printf("read file %s complete, size=%d.\n",filename,size);  

    cJSON_to_struct_array(buf, worker);  
 
    free(buf);  
}  


int main(int argc, char **argv)  
{  
 
    read_file(FILENAME);  
 
    return 0;  
}  

编译:

gcc cJSON.c test_cJSON.c -o test_cJSON  -lm

输出结果:

在这里插入图片描述
解析一个结构体,下面咱看看这类型的结构体怎么解

{
         "person":
         {
                   "firstName":"minger",
                   "lastName":"ming",
                   "email":"[email protected]",
                   "age":18,
                   "height":1.77
         }        
}

需要用到接口函数

cJSON*cJSON_Parse(const char *value); 
cJSON*cJSON_GetObjectItem(cJSON *object,const char *string);
voidcJSON_Delete(cJSON *c); 

解析一个结构体

int cJSON_to_struct(char *json_string, people *person)  
{  
    cJSON *item;  
    cJSON *root=cJSON_Parse(json_string);  
    if (!root)  
    {  
        printf("Error before: [%s]\n",cJSON_GetErrorPtr());  
        return -1;  
    }  
    else 
    {  
        cJSON *object=cJSON_GetObjectItem(root,"person");  
        if(object==NULL)  
        {  
            printf("Error before: [%s]\n",cJSON_GetErrorPtr());  
            cJSON_Delete(root);  
            return -1;  
        }  
        printf("cJSON_GetObjectItem: type=%d, key is %s, value is %s\n",object->type,object->string,object->valuestring);  
 
        if(object!=NULL)  
        {  
            item=cJSON_GetObjectItem(object,"firstName");  
            if(item!=NULL)  
            {  
                printf("cJSON_GetObjectItem: type=%d, string is %s, valuestring=%s\n",item->type,item->string,item->valuestring);  
                memcpy(person->firstName,item->valuestring,strlen(item->valuestring));  
            }  
 
            item=cJSON_GetObjectItem(object,"lastName");  
            if(item!=NULL)  
            {  
                printf("cJSON_GetObjectItem: type=%d, string is %s, valuestring=%s\n",item->type,item->string,item->valuestring);  
                memcpy(person->lastName,item->valuestring,strlen(item->valuestring));  
            }  
 
            item=cJSON_GetObjectItem(object,"email");  
            if(item!=NULL)  
            {  
                printf("cJSON_GetObjectItem: type=%d, string is %s, valuestring=%s\n",item->type,item->string,item->valuestring);  
                memcpy(person->email,item->valuestring,strlen(item->valuestring));  
            }  
 
            item=cJSON_GetObjectItem(object,"age");  
            if(item!=NULL)  
            {  
                printf("cJSON_GetObjectItem: type=%d, string is %s, valueint=%d\n",item->type,item->string,item->valueint);  
                person->age=item->valueint;  
            }  
            else 
            {  
                printf("cJSON_GetObjectItem: get age failed\n");  
            }  
 
            item=cJSON_GetObjectItem(object,"height");  
            if(item!=NULL)  
            {  
                printf("cJSON_GetObjectItem: type=%d, string is %s, valuedouble=%f\n",item->type,item->string,item->valuedouble);  
                person->height=item->valuedouble;  
            }  
        }  
 
        cJSON_Delete(root);  
    }  
 return 0;  
}  

总结

相比于python一条搞定解析来说,C语言中解析JSON似乎显得有些麻烦,但cJSON无疑是一个超轻量级的JSON器。cJSON只需一个C文件,一个头文件,包含到项目源码中即可解析。

发布了71 篇原创文章 · 获赞 42 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/chen1415886044/article/details/103395027