Linux(程序设计):30---cJSON库(C语言操作JSON)

一、cJSON库概述

cJSON库的编译安装

  • 下载cJSON源码
git clone https://github.com/DaveGamble/cJSON.git

  • 下载完成之后有一个cJSON目录

  • 下载完成之后进入cJSON目录,在里面建立一个build目录,然后进入build目录,输入cmake ..
cd cJSON

mkdir build

cd build

cmake ..

  • 然后回到顶级目录,可以看到目录下生成了一个Makefile文件,此时输入make对cJOSN进行编译

  • 编译完成之后进行安装

  • 默认情况下,cJSON的头文件安装到/usr/local/include/cjson/目录下,动态库文件安装到/usr/local/lib/目录下,相关cmake文件安装到/usr/local/lib/cmake/cJSON/目录下

  • 因为头文件默认安装在/usr/local/include/cjson/目录下,因此编译程序的时候如果用到cJSON.h这个头文件会显示不存在,如下图所示

  • 因此我们需要将/usr/local/include/cjson/cJSON.h移动到/usr/local/include/目录下,如下所示

  • 备注:其实我们不需要将cJSON.h文件从/usr/local/include/cjson/目录下移动到/usr/local/include/目录下,如果不移动的话那么就编写代码时带上include "cjson/cJSON.H"头文件即可,只不过有cjson/前缀比较麻烦

编译运行带有cJSON库的程序

  • 有两种方式:
    • ①方式一:像上面一样,将cJSON安装,然后将cJONS.h拷贝到/usr/local/include/目录下,然后将源码目录下的cJOSN.c文件拷贝到项目目录下
    • ②方式二:不用像上面一样安装cJSON,直接将cJSON源码目录下的cJSON.h和cJSON.c文件拷贝到项目下就可以编译使用了
  • 编译程序时使用下面的命令:
# 因为cJSON源码中使用到了数学函数库, 因此需要使用-lm选项
gcc cJSON.c demo.c -o demo -lm
  • 编译的过程中可能会遇到的问题:
    • 遇到cJSON.h头文件不识别的问题:确保cJSON.h位于你的程序可以找到的地方,如果在其他地方可以指定gcc -I参数进行编译
    • 不仅要有cJSON.h头文件,程序编译时还要需要cJSON.c文件,因此需要将cJSON库下的cJSON.c拷贝到自己的项目中进行编译
    • cJSON不同版本之间源码不同,因此需要确保使用的cJSON.h和cJSON.c是同一版本的,否则会编译不通过

二、cJSON库重要的数据结构与类型

cJSON结构

  • cJSON结构定义在cJSON.h头文件中,每个JSON对象就是用这个结构表示的
/* The cJSON structure: */
typedef struct cJSON {
    struct cJSON *next,*prev;	/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
    struct cJSON *child;		/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */

    int type;					/* The type of the item, as above. */

    char *valuestring;			/* The item's string, if type==cJSON_String */
    int valueint;				/* The item's number, if type==cJSON_Number */
    double valuedouble;			/* The item's number, if type==cJSON_Number */

    char *string;				/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} cJSON;
  • next、prev:用于遍历数组或对象链的前后向后链表指针
  • child:指向数组或对象的孩节点
  • type:代表一个JSON是value的类型
  • valuestring:如果value是字符串类型,则该值指向于value
  • valueint:如果value是整数类型,则该值指向于value
  • valuedouble:如果value是浮点数类型,则该值指向于value
  • string是key的名字

cJSON支持的类型

  • 下面是一些宏定义,就是cJOSN结构中type字段可以取得值,代表值的类型
/* cJSON Types: */
#define cJSON_False 0
#define cJSON_True 1
#define cJSON_NULL 2
#define cJSON_Number 3
#define cJSON_String 4
#define cJSON_Array 5
#define cJSON_Object 6

三、重点函数

cJSON_Parse

cJSON *cJSON_Parse(const char *value);
  • 作用:参数传递一个JSON字符串,将该字符串转换为一个cJSON对象进行返回(该对象是在内存中动态申请的,因此需要用下面的cJSON_Delete进行释放)
  • 返回值:
    • 成功:返回一个指向内存中的cJSON的指针
    • 失败:返回NULL

cJSON_Delete

void cJSON_Delete(cJSON *c);
  • 作用:释放位于堆中的cJSON结构体内存
  • 无返回值
  • 备注:
    • 在使用cJSON_Parse创建cJSON对象之后,如果该对象不再使用了,需要释放该对象,否则导致内存泄漏
    • 其他有些API也会创建cJSON对象,在申请用完之后也需要释放

cJSON_Print

char  *cJSON_Print(cJSON *item);
  • 作用:将cJSON对象解析成一个字符串进行返回,并在堆中开辟一块char*的内存空间存储该字符串
  • 返回值:
    • 成功:返回一个指向char*指针指向位于堆中的JSON字符串
    • 失败:返回NULL
  • 备注:
    • 通过cJSON_Print()可以将cJSON链表中所有的cJSON对象打印出来
    • cJSON_PrintUnformatted()与 cJSON_Print()类似,只是打印输出不带格式,而只是一个 字符串数据
    • 因为返回值是该函数自动申请的,因此在使用完之后需要使用free()释放该函数返回值的内存空间

cJSON_Version

const char* cJSON_Version(void);
  • 作用:将返回当前使用的cJSON库的版本号
  • 返回值:一个表示当前版本的字符串

cJSON_GetArrayItem

cJSON *cJSON_GetArrayItem(cJSON *array,int item);
  • 作用:如果array是一个数组类型的,则返回数组中item索引处的cJSON对象
  • 返回值:
    • 成功:返回一个指向cJSON类型的结构体指针
    • 失败:返回NULL

cJSON_GetArraySize

int cJSON_GetArraySize(cJSON *array);
  • 作用:如果array是一个数组类型,返回数组中对应元素的个数
  • 返回值:
    • 有元素:返回元素的个数
    • 无元素:返回0
  • 与上面类似的接口还有cJSON_GetObjectItem()和cJSON_HashObjectItem()

四、所有函数简介

扫描二维码关注公众号,回复: 11329674 查看本文章

五、演示案例1

 代码如下

//demo1.c
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
#include <string.h>

/**
{
	"name":	"milo",
	"age":	80,
	"professional": {专业
        "english": 4,
        "putonghua": 2,
        "computer": 4
    },
    "languages":	["C++", "C"],
	"phone":	{
		"number":	"18620823143",
		"type":	"home"
	},
	"courses":	[{
			"name":	"Linux kernel development",
			"price":	"7.7"
		}, {
			"name":	"Linux server development",
			"price":	"8.0"
		}],
	"vip":	true,
	"address":	null
}
*/

//打印CJSON
void printfJson(cJSON *json) {
    if (NULL == json) {
        return;
    }
    char *cjson=cJSON_Print(json);//深拷贝
    printf("json:%s\n", cjson);
    free(cjson);
}

//释放
void freeJson(cJSON *json) {
    if (json != NULL) {
        cJSON_Delete(json);
	}
}

//创建JSON
cJSON * createJson() {
	//创建根节点JSON(最外面大括号的JSON对象)
    cJSON *json_root=cJSON_CreateObject();
	cJSON_AddItemToObject(json_root, "name", cJSON_CreateString("milo"));
	cJSON_AddNumberToObject(json_root, "age", 80);

	//下面是4个内部JSON对象(包含在根JSON内部的)
    cJSON *json_professional=cJSON_CreateObject();
    cJSON_AddItemToObject(json_professional,"english", cJSON_CreateNumber(4));
    cJSON_AddItemToObject(json_professional,"putonghua", cJSON_CreateNumber(2));
    cJSON_AddItemToObject(json_professional,"computer", cJSON_CreateNumber(3));

    cJSON *json_languages=cJSON_CreateArray(); //注意: 这是一个数组
    cJSON_AddItemToArray(json_languages, cJSON_CreateString("C++"));
    cJSON_AddItemToArray(json_languages, cJSON_CreateString("C"));

    cJSON *json_phone=cJSON_CreateObject();
    cJSON_AddItemToObject(json_phone,"number", cJSON_CreateString("18620823143"));
    cJSON_AddItemToObject(json_phone,"type", cJSON_CreateString("home"));

    cJSON *json_courses = cJSON_CreateArray(); //注意: courses也是一个数组, 其内部有两个对象
    cJSON* json_pItem1 = cJSON_CreateObject();
    cJSON_AddItemToObject(json_pItem1, "name", cJSON_CreateString("Linux kernel development"));
    cJSON_AddNumberToObject(json_pItem1, "price", 7.7);
    cJSON_AddItemToArray(json_courses, json_pItem1);

    cJSON* json_pItem2 = cJSON_CreateObject();
    cJSON_AddItemToObject(json_pItem2, "name", cJSON_CreateString("Linux server development"));
    cJSON_AddNumberToObject(json_pItem2, "price", 8.8);
    cJSON_AddItemToArray(json_courses, json_pItem2);


	//将这个几个内部JSON添加到根节点JSON对象中
    cJSON_AddItemToObject(json_root, "professional", json_professional);
    cJSON_AddItemToObject(json_root, "languages", json_languages);
    cJSON_AddItemToObject(json_root, "phone", json_phone);
    cJSON_AddItemToObject(json_root, "courses", json_courses);

    cJSON_AddBoolToObject(json_root, "vip", 1);
    cJSON_AddNullToObject(json_root, "address");

    return json_root;
}

//向已有的cJSON对象中添加数据(此函数以添加到根节点为例)
//如果要添加到根cJSON对象内部的cJSON对象中(例如添加到professional中), 需要解析cJSON对象, 可以参阅下面的analysisJsonObj()函数
//"hobby": ["Basketball", "Football", "badminton"],
void addDataToJson(cJSON *json) {
    if (NULL == json) {
        return;
    }

    cJSON *hobby=cJSON_CreateArray();
    cJSON_AddItemToArray(hobby, cJSON_CreateString("Basketball"));
    cJSON_AddItemToArray(hobby, cJSON_CreateString("Football"));
    cJSON_AddItemToArray(hobby, cJSON_CreateString("badminton"));

    /*
    CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
    */
    cJSON_AddItemToObject(json, "hobby", hobby);

    printfJson(json);
}

//修改cJSON对象
//例如将 "hobby": ["Basketball", "Football", "badminton"], 修改为"hobby": ["Skating", "dance"],
void updateDataToJson(cJSON *json) {
    if (NULL == json) {
        return;
    }

    cJSON *hobby=cJSON_CreateArray();
    cJSON_AddItemToArray(hobby, cJSON_CreateString("Skating"));
    cJSON_AddItemToArray(hobby, cJSON_CreateString("dance"));

    /*
    CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
    CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
    */
	
	//修改替换
    cJSON_ReplaceItemInObject(json, "hobby", hobby);

    printfJson(json);
}

//删除
//例如删除"hobby": ["Skating", "dance"],
void deleteDataToJson(cJSON *json) {
    if (NULL == json) {
        return;
    }

    /*
    CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
    */
    cJSON_DetachItemFromObject(json, "hobby");

    printfJson(json);
}

//解析JSON
void analysisJsonObj(cJSON *json) {
    if (NULL == json) {
        return;
    }

	//解析name
    cJSON *json_name = cJSON_GetObjectItem(json, "name");
    printf("root[%s:%s]\n", json_name->string, json_name->valuestring);
	//解析age
    cJSON *json_age = cJSON_GetObjectItem(json, "age");
    printf("root[%s:%d]\n", json_age->string, json_age->valueint);
	
	//解析professional, 通过调用child和next遍历解析
    cJSON *json_professional = cJSON_GetObjectItem(json, "professional");
    cJSON *json_professional_child = json_professional->child;
    while (json_professional_child != NULL) {
        printf("%s[%s:%d]\n", json_professional->string, json_professional_child->string, json_professional_child->valueint);
        json_professional_child = json_professional_child->next;

    }
	
	//解析languages, 注意languages是一个数组
    cJSON *json_languages = cJSON_GetObjectItem(json, "languages");
    if (json_languages) {
        int size = cJSON_GetArraySize(json_languages);
        printf("%s size:%d\n", json_languages->string, size);
        for (int i = 0; i < size; i++) {
            cJSON *json_languages_child =cJSON_GetArrayItem(json_languages, i);
            printf("%s[%d:%s]\n", json_languages->string, i, json_languages_child->valuestring);
        }
    }

	//解析phone. 另一种方式解析, 直接通过名字获取
    cJSON *json_phone = cJSON_GetObjectItem(json, "phone");
    cJSON *json_phone_number = cJSON_GetObjectItem(json_phone,"number");
    cJSON *json_phone_type = cJSON_GetObjectItem(json_phone,"type");
    printf("%s[%s:%s]\n", json_phone->string, json_phone_number->string, json_phone_number->valuestring);
    printf("%s[%s:%s]\n", json_phone->string, json_phone_type->string, json_phone_type->valuestring);

	//解析courses
    cJSON *json_courses = cJSON_GetObjectItem(json, "courses");
    if (json_courses) {
        int size = cJSON_GetArraySize(json_courses);
        printf("%s size:%d\n", json_courses->string, size);
        for(int i=0;i<size;i++) {
            cJSON *json_array = cJSON_GetArrayItem(json_courses, i);
            if (json_array) {
                cJSON *json_course_name = cJSON_GetObjectItem(json_array,"name");
                cJSON *json_course_price = cJSON_GetObjectItem(json_array,"price");
                printf("%s[%s:%.1lf]\n", json_courses->string, json_course_name->string, json_course_name->valuedouble);
                printf("%s[%s:%.1lf]\n", json_courses->string, json_course_price->string, json_course_price->valuedouble);
            }
        }
    }

	//解析vip, vip是布尔值, 有两种方式解析获取
    cJSON *json_vip = cJSON_GetObjectItem(json, "vip");
    /*
    if (json_vip->type == cJSON_True) {
        printf("root[%s:true]\n", json_vip->string);
    } else if (json_vip->type == cJSON_False) {
        printf("root[%s:false]\n", json_vip->string);
    } else {
        printf("root[%s:false]\n", json_vip->string);
    }
    */
    cJSON_bool bvip = cJSON_IsBool(json_vip);
    if (bvip == cJSON_True) {//cJSON_False
        printf("root[%s:true]\n", json_vip->string);
    } else {
        printf("root[%s:false]\n", json_vip->string);
    }

	//解析address
    cJSON *json_address = cJSON_GetObjectItem(json, "address");
    if (json_address->type ==cJSON_NULL) {
        printf("root[%s:null]\n", json_address->string);
    }
}


//获取cJSON对象的类型, 并同时打印值
static void printJsonObjvalue(const cJSON *json) {
    if (NULL == json) {
        printf("NULL object!\n");
        return;
    }

    switch (json->type) {
        case cJSON_False:
            printf("%s: false\n", json->string);
            break;
        case cJSON_True:
            printf("%s: true\n", json->string);
            break;
        case cJSON_NULL:
            printf("%s: cJSON_NULL\n", json->string);
            break;
        case cJSON_Number:
            printf("%s: %d, %f\n", json->string, json->valueint, json->valuedouble);
            break;
        case cJSON_String:
            printf("%s: %s\n", json->string, json->valuestring);
            break;
        case cJSON_Array:
            printf("%s: cJSON_Array\n", json->string);
            break;
        case cJSON_Object:
            printf("%s: cJSON_Object\n", json->string);
            break;
        default:
            printf("unknown type\n");
            break;
    }
}


void analysisJsonPrint(cJSON *json) {
    if (NULL == json) {
        return;
    }

    cJSON *json_name = cJSON_GetObjectItem(json, "name");
    printJsonObjvalue(json_name);

    cJSON *json_age = cJSON_GetObjectItem(json, "age");
    printJsonObjvalue(json_age);

    cJSON *json_professional = cJSON_GetObjectItem(json, "professional");
    cJSON *json_professional_child = json_professional->child;
    while (json_professional_child != NULL) {
        printJsonObjvalue(json_professional_child);
        json_professional_child = json_professional_child->next;
    }

    cJSON *json_languages = cJSON_GetObjectItem(json, "languages");
    if (NULL == json_languages) {
        int size = cJSON_GetArraySize(json_languages);
        printf("%s size:%d\n", json_languages->string, size);
        for (int i = 0; i < size; i++) {
            cJSON *json_languages_child = cJSON_GetArrayItem(json_languages, i);
            printJsonObjvalue(json_languages_child);
        }
    }

    cJSON *json_phone = cJSON_GetObjectItem(json, "phone");
    cJSON *json_phone_number = cJSON_GetObjectItem(json_phone,"number");
    cJSON *json_phone_type = cJSON_GetObjectItem(json_phone,"type");
    printJsonObjvalue(json_phone_number);
    printJsonObjvalue(json_phone_type);

    cJSON *json_courses = cJSON_GetObjectItem(json, "courses");
    if (json_courses) {
        int size = cJSON_GetArraySize(json_courses);
        printf("%s size:%d\n", json_courses->string, size);
        for(int i=0;i<size;i++) {
            cJSON *arrayItem = cJSON_GetArrayItem(json_courses, i);
            if (NULL != arrayItem) {
                cJSON *json_course_name = cJSON_GetObjectItem(arrayItem,"name");
                cJSON *json_course_price = cJSON_GetObjectItem(arrayItem,"price");
                printJsonObjvalue(json_course_name);
                printJsonObjvalue(json_course_price);
            }
        }
    }

    cJSON *json_vip = cJSON_GetObjectItem(json, "vip");
    printJsonObjvalue(json_vip);

    cJSON *json_address = cJSON_GetObjectItem(json, "address");
    printJsonObjvalue(json_address);
}

//读取JSON
cJSON* readJsonFile(char *fileName) {
    if (NULL == fileName) {
        return NULL;
    }

    FILE *fp = NULL;
    cJSON *json = NULL;
    char line[1024] = {0};
    char *data = NULL;

    //打开一个文本文件,文件必须存在,只允许读
    fp = fopen(fileName, "r");
    if (NULL != fp) {
        //seek末尾
        fseek(fp, 0, SEEK_END);
        //读取文件大小
        long len = ftell(fp);
        //seek起始位值
        fseek(fp, 0, SEEK_SET);
        data = (char*)malloc(len + 1);
        fread(data, 1, len, fp);
        fclose(fp);
    }
    
    printf("readJsonFile data:%s\n", data);
    cJSON *json_root = cJSON_Parse(data);
    if (NULL == json_root) {
        printf("cJSON_Parse error:%s\n", cJSON_GetErrorPtr());
    }

    if (NULL != data) {
        free(data);
    }

    return json_root;
}

//保存JSON
void writeJsonFile(char *fileName, cJSON *json) {
    if (NULL == json || NULL == fileName) {
        return;
    }

    char *cjson=cJSON_Print(json);

    FILE *fp = NULL;
    //新建一个文本文件,已存在的文件将内容清空,允许读写
    fp = fopen(fileName, "w+");
    if (NULL != fp) {
        fwrite(cjson, strlen(cjson),1,fp);
        fclose(fp);
	}

    if (NULL != cjson) {
        free(cjson);
	}
}

void test1() {
    cJSON *json_root = createJson();
    //打印
    printfJson(json_root);
    //解析json
    analysisJsonObj(json_root);
    //解析json
    analysisJsonPrint(json_root);
    freeJson(json_root);
}

void test2() {
    char *fileName = "./person.json";

    //读取json
    cJSON *json_root = readJsonFile(fileName);
    //解析json
    analysisJsonObj(json_root);
    //解析json
    analysisJsonPrint(json_root);

    //写入json文件
    writeJsonFile(fileName, json_root);

    //释放
    freeJson(json_root);
}

//增删改
void test3() {
    cJSON *json_root = createJson();

    addDataToJson(json_root);

    updateDataToJson(json_root);

    deleteDataToJson(json_root);

    freeJson(json_root);
}

int main(int argc, char *argv[]) {
    
    printf("-----------------------------------\n");
    test1();
    printf("-----------------------------------\n");
    test2();
    printf("-----------------------------------\n");
    test3();
    printf("-----------------------------------\n");

    return 0;
}
  • 编译如下:
gcc cJSON.c demo1.c -o demo1 -lm

  • 效果如下(只截取部分):

 

六、演示案例2

 代码如下

//comment_test.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include "cJSON.h"
#include <string.h>


//评论
typedef struct COMMENT
{
    int user_id;
    int msg_id;
    char* comment;
    int click_count;
    int like_count;
    int reply_count;
    int is_new_reply;
    long add_time;
} COMMENT;

//例如
/**
json对象
{
    "user_id":1,
    "msg_id":1,
    "comment":"json",
    "click_count":0,
    "like_count":0,
    "reply_count":0,
    "is_new_reply":0,
    "add_time":0,
}
*/


//获取当前时间毫秒数
long getCurrentTime()
{
    struct timeval tv;
    gettimeofday(&tv,NULL);
    //毫秒
    long time_sec = tv.tv_sec*1000 + tv.tv_usec/1000;

    return time_sec;
}

//打印CJSON
void printfJson(cJSON *json) {
    if (NULL == json) {
        return;
    }
    char *cjson=cJSON_Print(json);//深拷贝
    printf("json:%s\n", cjson);
    free(cjson); //因为调用了cJSON_Print(), 因此需要手动释放资源
}

void freeComment(COMMENT *comment) {
    if (comment != NULL) {
        if (comment->comment != NULL) {
            free(comment->comment);
            comment->comment = NULL;
        }

        free(comment);
        comment = NULL;
    }
}

void freeJson(cJSON *json) {
    if (json != NULL) {
        cJSON_Delete(json);
	}
}

//将结构体转成cJSON
cJSON *convertToJson(COMMENT *comment) 
{
    if (comment == NULL)
        return NULL;

    //创建json
    cJSON *json=cJSON_CreateObject();
    
	//将 "user_id" 添加到 "json" 节点
	cJSON_AddNumberToObject(json, "user_id", comment->user_id);
	cJSON_AddNumberToObject(json, "msg_id", comment->msg_id);
    cJSON_AddItemToObject(json, "comment", cJSON_CreateString(comment->comment));//调用cJSON_CreateString()将字符串转换为JSON中的字符串类型,否则报错
    cJSON_AddNumberToObject(json, "click_count", comment->click_count);
    cJSON_AddNumberToObject(json, "like_count", comment->like_count);
    cJSON_AddNumberToObject(json, "reply_count", comment->reply_count);
    cJSON_AddNumberToObject(json, "is_new_reply", comment->is_new_reply);
    cJSON_AddNumberToObject(json, "add_time", comment->add_time);
	//user_id等的value都是int类型的,因此使用cJSON_AddNumberToObject. 而comment是字符串类型的,因此使用cJSON_AddItemToObject

    return json;
}

//解析cJSON对象, 将cJSON赋值给结构体
COMMENT* convertToComment(cJSON *json)
{  
    if (NULL == json) {
        return NULL;
    }
   
    //通cJSON对象中获取内容
    cJSON *json_user_id = cJSON_GetObjectItem(json, "user_id");
    cJSON *json_msg_id = cJSON_GetObjectItem(json, "msg_id");
    cJSON *json_comment = cJSON_GetObjectItem(json, "comment");
    cJSON *json_click_count = cJSON_GetObjectItem(json, "click_count");
    cJSON *json_like_count = cJSON_GetObjectItem(json, "like_count");
    cJSON *json_reply_count = cJSON_GetObjectItem(json, "reply_count");
    cJSON *json_is_new_reply = cJSON_GetObjectItem(json, "is_new_reply");
    cJSON *json_add_time = cJSON_GetObjectItem(json, "add_time");

	//将内容赋值给结构体
    COMMENT *comment = (COMMENT *)malloc(sizeof(COMMENT));
    comment->user_id = json_user_id->valueint;             //user_id等是使用int来存储的, 因此使用cJSON对象的valueint成员来获取(下同)
    comment->msg_id = json_msg_id->valueint;
    comment->comment=(char *)malloc(256);
    memset(comment->comment, 0, 256);
    strcat(comment->comment, json_comment->valuestring);   //comment是使用字符串来存储的, 因此使用cJSON对象的valuestring成员来获取(下同)
    comment->click_count = json_click_count->valueint;
    comment->like_count = json_like_count->valueint;
    comment->reply_count = json_reply_count->valueint;
    comment->is_new_reply = json_is_new_reply->valueint;
    comment->add_time = (long)(json_add_time->valuedouble); //C中使用long来存储时间, 在cJSON中使用double来存储

    return comment;
}

//从数据中读取数据
void readJsonFromData(char *data) {
    cJSON *json=cJSON_Parse(data);//将data数据构建成cJSON结构
    //打印json
    printfJson(json);

    COMMENT* comment = convertToComment(json);
    if (comment != NULL) {
        
        comment->like_count = 77;
        comment->reply_count = 99;

        //转为json
        cJSON *childjson = convertToJson(comment);
        //打印json
        printfJson(childjson);
        //释放对象
        freeComment(comment);
        //
        freeJson(childjson);
	}
	
	//cJSON_Parse()返回的cJSON对象需要手动释放资源
    freeJson(json);
}

//保存JSON
void writeJsonFile(cJSON *json) {
    if (NULL == json) {
        return;
    }

    char *cjson=cJSON_Print(json);

    FILE *fp = NULL;
    char *fileName = "./comment.json";
    fp = fopen(fileName, "w+");
    if (NULL != fp) {
        fwrite(cjson, strlen(cjson),1,fp);
        fclose(fp);
	}
    if (cjson != NULL) {
        free(cjson);
	}
}

//读取JSON
void readJsonFile() {
    FILE *fp = NULL;
    char *out;
    char line[1024] = {0};
    char *fileName = "./comment.json";

    //打开一个文本文件,文件必须存在,只允许读
    fp = fopen(fileName, "r");
    //seek末尾
    fseek(fp, 0, SEEK_END);
    //读取文件大小
    long len = ftell(fp);
    //seek起始位值
    fseek(fp, 0, SEEK_SET);
    char *data = (char*)malloc(len + 1);
    fread(data, 1, len, fp);
    if (fp != NULL) {
        fclose(fp);
	}

    //读取
    readJsonFromData(data);
    
    if (NULL != data) {
        free(data);
    }
}

COMMENT *createComment() {
    COMMENT *comment = (COMMENT *)malloc(sizeof(COMMENT));
    comment->user_id = 1;
    comment->msg_id = 10000;
    comment->comment=(char *)malloc(256);
    memset(comment->comment, 0, 256);
    sprintf(comment->comment, "我赞同楼主");
    comment->click_count = 0;
    comment->like_count = 0;
    comment->reply_count = 0;
    comment->is_new_reply = 0;
    comment->add_time = getCurrentTime();
    return comment;
}

void test1() {
    COMMENT *comment = createComment();

    //转为json
    cJSON *json = convertToJson(comment);
    
    //保存json
    writeJsonFile(json);

    freeComment(comment);

    freeJson(json);
}

void test2() {
    //读取json
    readJsonFile();
}

int main(int argc, char *argv[]) {
    
    test1();

    test2();

    return 0;
}
  • 编译如下:
gcc cJSON.c comment_test.c -o comment_test -lm

  • 效果如下: 

猜你喜欢

转载自blog.csdn.net/qq_41453285/article/details/106699410