- cJSON库的使用详情
- 什么是JSON?
- 一、cJSON动态库制作:
- 二、cJSON介绍
- 1.json数据表示方式
- 2.cJSON的结构体
- 3.cJSON宏定义的类型type
- 4.字符串生成的cJSON指针的函数,使用后需要调用cJSON_Delete进行释放
- 5.cjson指针指针生成字符串的函数
- 三、封装JSON数据
- 1.定义对象{},添加**键值对** :{"name":"client"}
- 2.定义数组[],添加**值**:["red","green","blue"]
- 3.数组嵌套[[],[]]:[["xx","xx"],["xx","xx"]]
- 4.对象嵌套对象{{},{}}:{"xx":{"xx":"xx"},"xx":{"xx":"xx"}}:
- 5.对象嵌套数组对象{ [{},{}] }:{"xx":[{"xx":"xx"},{"xx":"xx"}]}
- 完整代码:main.c
- 四、解析JSON数据
- 1.读取.json文件
- 2.通过cJSON_Parse函数解析jsonStr字符串
- 3.直接进行解析
- 4.解析数组
- 5.解析{{},{}}
JSON(JavaScript Object Notation)是一个用于数据交换的文本格式,现时的标准为ECMA-404。
JSON 是轻量级的文本数据交换格式,几乎所有与网页开发相关的语言都有JSON库。
JSON比XML更小、更快,JSON是一种开放的、轻量级的数据交换格式,采用独立于编程语言的文本格式来存储和表示数据,易于程序员阅读与编写,同时也易于计算机解析和生成,通常用于在 Web 客户端(浏览器)与 Web 服务器端之间传递数据。
例如,一个动态网页想从服务器获得数据时,服务器从数据库查找数据,然后把数据转换成 JSON 文本格式:
{
"title": "Design Patterns",
"subtitle": "Elements of Reusable Object-Oriented Software",
"author": [
"Erich Gamma",
"Richard Helm",
"Ralph Johnson",
"John Vlissides"
],
"year": 2009,
"weight": 1.8,
"hardcover": true,
"publisher": {
"Company": "Pearson Education",
"Country": "India"
},
"website": null
}
从此例子可看出,JSON 是树状结构,而 JSON 只包含 6 种数据类型:
- null: 表示为 null
- boolean: 表示为 true 或 false
- number: 一般的浮点数表示方式
- string: 表示为 “…”
- array: 表示为 [ … ]
- object: 表示为 { … }
实现的 JSON 库,主要是完成 3 个需求:
- 把 JSON 文本解析为一个树状数据结构(parse)。
- 提供接口访问该数据结构(access)。
- 把数据结构转换成 JSON 文本(stringify)。
1.下载cJSON开源库:cJSON库
2.把这两个文件放到目录中
3.制作动态库cjson
gcc -shared -fPIC cJSON.c -o libcjson.so
-shared :表示生成的是.so动态库文件
-fPIC:表示代码和地址无关,不需要被不同模块重定位,生成PIC代码。为了达到动态链接的目的。
sudo cp libcjson.so /lib
- 运行程序时需要将库文件拷贝到 /usr/lib 或者/lib 中才能运行.
- 或者把库所在的路径添加到/etc/ld.so.conf, 执行ldconfig /etc/ld_so.conf
4.编译运行
gcc xx.c -lcjson -lm ./a.out二、cJSON介绍 1.json数据表示方式
在json中使用两种方式表示数据
-
Object(对象):键/值对的集合,使用**{ }**定义。在以键开头,后跟冒号:最后是值,多个键/值之间用 **,**逗号分隔
-
Array(数组):值的有序集合,使用 []定义,数组中每个值之间用逗号**,**分隔
typedef struct cJSON {
struct cJSON *next,*prev;
struct cJSON *child;
int type;
char *valuestring;
int valueint;
double valuedouble;
char *string;
} cJSON;
3.cJSON宏定义的类型type
#define cJSON_False 0 //false #define cJSON_True 1 //true #define cJSON_NULL 2 //NULL #define cJSON_Number 3 //数字 #define cJSON_String 4 //字符串 #define cJSON_Array 5 //数组 #define cJSON_Object 6 //对象4.字符串生成的cJSON指针的函数,使用后需要调用cJSON_Delete进行释放
extern cJSON *cJSON_Parse(const char *value); // 释放cJSON_Parse返回的指针 extern void cJSON_Delete(cJSON *c);5.cjson指针指针生成字符串的函数
// 这个生成的字符串有做格式调整 extern char *cJSON_Print(cJSON *item); // 这个没有作格式调整,就是一行字符串显示 extern char *cJSON_PrintUnformatted(cJSON *item); // Free the char* when finished.否则会造成内存泄漏三、封装JSON数据 1.定义对象{},添加键值对 :{“name”:“client”}
main.c
#include#include #include #include #include #include "cJSON.h" #define JSON_PATH "./config.json" void main(int argc, char const *argv[]) { FILE *file=NULL; file = fopen(JSON_PATH,"w+"); if(file == NULL) { perror("fopen"); return ; } cJSON *root; //定义对象{ } root = cJSON_CreateObject(); //插入元素 键值对"name":"client" cJSON_AddItemToObject(root,"name",cJSON_CreateString("client")); char *s = cJSON_Print(root); printf("%sn",s); fwrite(s,sizeof(char),strlen(s),file); free(s); fclose(file); cJSON_Delete(root); return ; } //gcc main.c -lcjson -lm
效果如下:
2.定义数组[],添加值:[“red”,“green”,“blue”]cJSON *colorArray;
colorArray = cJSON_CreateArray(); //[]
cJSON_AddItemToArray(colorArray,cJSON_CreateString("red"));
cJSON_AddItemToArray(colorArray,cJSON_CreateString("green"));
cJSON_AddItemToArray(colorArray,cJSON_CreateString("blue"));
//colorArray ["red","green","blue"]
cJSON_AddItemToObject(root,"color",colorArray);
效果如下:
3.数组嵌套[[],[]]:[[“xx”,“xx”],[“xx”,“xx”]]//[[""],[""]]
cJSON *languageArray,*usaArr,*ukArr;
languageArray = cJSON_CreateArray();
usaArr = cJSON_CreateArray();
ukArr = cJSON_CreateArray();
cJSON_AddItemToArray(usaArr,cJSON_CreateString("USA"));
cJSON_AddItemToArray(usaArr,cJSON_CreateString("American English"));
cJSON_AddItemToArray(ukArr,cJSON_CreateString("UK"));
cJSON_AddItemToArray(ukArr,cJSON_CreateString("British English"));
//usaArr ["USA","American English"]
//ukArr ["UK","British English"]
cJSON_AddItemToArray(languageArray,usaArr);
cJSON_AddItemToArray(languageArray,ukArr);
//languageArray [["USA", "American English"], ["UK", "British English"]]
cJSON_AddItemToObject(root,"Languages",languageArray);
效果如下:
4.对象嵌套对象{{},{}}:{“xx”:{“xx”:“xx”},“xx”:{“xx”:“xx”}}:“address”:{“南方”:{“city”:“四川成都”,“street”:“建设路”},“北方”:{“city”:“北京”,“street”:“长安街”}}
cJSON *address,*cdCity,*bjCity;
address = cJSON_CreateObject();
cdCity = cJSON_CreateObject();
bjCity = cJSON_CreateObject();
cJSON_AddItemToObject(cdCity,"street",cJSON_CreateString("成华大道"));
cJSON_AddItemToObject(cdCity,"city",cJSON_CreateString("四川成都"));
//cdCity {"city":"四川成都","street":"建设路"}
cJSON_AddItemToObject(bjCity,"street",cJSON_CreateString("长安街"));
cJSON_AddItemToObject(bjCity,"city",cJSON_CreateString("北京"));
//cjCity {"city":"北京","street":"长安街"}
cJSON_AddItemToObject(address,"南方",cdCity);
cJSON_AddItemToObject(address,"北方",bjCity);
//address {"南方":{"city":"四川成都","street":"建设路"},"北方":{"city":"北京","street":"长安街"}}
cJSON_AddItemToObject(root,"address",address);
效果如下:
{“links”:[{“name”:“Google”,“url”:“http://www.google.com”},{“name”:“Baidu”,“url”:“http://www.baidu.com”}]}
cJSON *linkArry,*obj1,*obj2;
linkArry = cJSON_CreateArray(); //[]定义数组
obj1 = cJSON_CreateObject(); //{}
cJSON_AddItemToObject(obj1,"name",cJSON_CreateString("Google"));
cJSON_AddItemToObject(obj1,"url",cJSON_CreateString("http://www.google.com"));
//obj1 {"name":"Google","url":"http://www.google.com"}
obj2 = cJSON_CreateObject();
cJSON_AddItemToObject(obj2,"name",cJSON_CreateString("Baidu"));
cJSON_AddItemToObject(obj2,"url",cJSON_CreateString("http://www.baidu.com"));
//obj2 {"name":"Baidu","url":"http://www.baidu.com"}
cJSON_AddItemToArray(linkArry,obj1);
cJSON_AddItemToArray(linkArry,obj2);
//linkArry [{"name":"Google","url":"http://www.google.com"},{"name":"Baidu","url":"http://www.baidu.com"}]
cJSON_AddItemToObject(root,"links",linkArry);
效果如下:
完整代码:main.c#include#include #include #include #include #include "cJSON.h" #define JSON_PATH "./config.json" void main(int argc, char const *argv[]) { FILE *file=NULL; file = fopen(JSON_PATH,"w+"); if(file == NULL) { perror("fopen"); return ; } // // extern cJSON *cJSON_CreateNull(void); // extern cJSON *cJSON_CreateTrue(void); // extern cJSON *cJSON_CreateFalse(void); // extern cJSON *cJSON_CreateBool(int b); // extern cJSON *cJSON_CreateNumber(double num); // extern cJSON *cJSON_CreateString(const char *string); // extern cJSON *cJSON_CreateArray(void); // extern cJSON *cJSON_CreateObject(void); // // extern cJSON *cJSON_CreateIntArray(const int *numbers,int count); // extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count); // extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count); // extern cJSON *cJSON_CreateStringArray(const char **strings,int count); cJSON *root; //定义 键值对 {"name":"client"} //{"":""} root = cJSON_CreateObject(); cJSON_AddItemToObject(root,"name",cJSON_CreateString("client")); cJSON_AddItemToObject(root,"cJSON_CreateNull",cJSON_CreateNull()); cJSON_AddItemToObject(root,"cJSON_CreateTrue",cJSON_CreateTrue()); cJSON_AddItemToObject(root,"cJSON_CreateFalse",cJSON_CreateFalse()); cJSON_AddItemToObject(root,"cJSON_CreateBool",cJSON_CreateBool(23)); cJSON_AddItemToObject(root,"cJSON_CreateBool0",cJSON_CreateBool(0)); cJSON_AddItemToObject(root,"cJSON_CreateNumber",cJSON_CreateNumber(9999999)); //["",""] cJSON *colorArray; colorArray = cJSON_CreateArray(); //[] cJSON_AddItemToArray(colorArray,cJSON_CreateString("red")); cJSON_AddItemToArray(colorArray,cJSON_CreateString("green")); cJSON_AddItemToArray(colorArray,cJSON_CreateString("blue")); cJSON_AddItemToObject(root,"color",colorArray); //[[""],[""]] cJSON *languageArray,*usaArr,*ukArr; languageArray = cJSON_CreateArray(); usaArr = cJSON_CreateArray(); ukArr = cJSON_CreateArray(); cJSON_AddItemToArray(usaArr,cJSON_CreateString("USA")); cJSON_AddItemToArray(usaArr,cJSON_CreateString("American English")); cJSON_AddItemToArray(ukArr,cJSON_CreateString("UK")); cJSON_AddItemToArray(ukArr,cJSON_CreateString("British English")); cJSON_AddItemToArray(languageArray,usaArr); cJSON_AddItemToArray(languageArray,ukArr); cJSON_AddItemToObject(root,"Languages",languageArray); // {"xx":{"xx":"xx"},"xx":{"xx":"xx"}} cJSON *address,*cdCity,*bjCity; address = cJSON_CreateObject(); cdCity = cJSON_CreateObject(); bjCity = cJSON_CreateObject(); cJSON_AddItemToObject(cdCity,"street",cJSON_CreateString("成华大道")); cJSON_AddItemToObject(cdCity,"city",cJSON_CreateString("四川成都")); cJSON_AddItemToObject(bjCity,"street",cJSON_CreateString("长安街")); cJSON_AddItemToObject(bjCity,"city",cJSON_CreateString("北京")); cJSON_AddItemToObject(address,"南方",cdCity); cJSON_AddItemToObject(address,"北方",bjCity); cJSON_AddItemToObject(root,"address",address); //{[{},{}]} cJSON *linkArry,*obj1,*obj2; linkArry = cJSON_CreateArray(); //[] obj1 = cJSON_CreateObject(); //{} cJSON_AddItemToObject(obj1,"name",cJSON_CreateString("Google")); cJSON_AddItemToObject(obj1,"url",cJSON_CreateString("http://www.google.com")); obj2 = cJSON_CreateObject(); cJSON_AddItemToObject(obj2,"name",cJSON_CreateString("Baidu")); cJSON_AddItemToObject(obj2,"url",cJSON_CreateString("http://www.baidu.com")); cJSON_AddItemToArray(linkArry,obj1); cJSON_AddItemToArray(linkArry,obj2); cJSON_AddItemToObject(root,"links",linkArry); char *s = cJSON_Print(root); printf("%sn",s); fwrite(s,sizeof(char),strlen(s),file); free(s); fclose(file); cJSON_Delete(root); return ; }
编译运行
gcc main.c -lcjson -lm ./a.out
效果如下:
stat获取文件信息:Linux文件属性
c语言标准IO:C语言标准IO
先通过stat获取文件大小,动态分配内存空间jsonStr,再fread读取
#include2.通过cJSON_Parse函数解析jsonStr字符串#include #include #include #include #include #include #include #include "cJSON.h" #define JSON_PATH "./config.json" void main(int argc, char const *argv[]) { FILE *file = NULL; int fileSize; char *jsonStr; struct stat statBuf; //文件属性结构体 file = fopen(JSON_PATH,"r"); if(file == NULL) { perror("fopen"); return; } stat(JSON_PATH, &statBuf); fileSize = statBuf.st_size; // printf("文件大小为:%dn",fileSize); // 分配内存 jsonStr = (char *)malloc(sizeof(char) * fileSize + 1); bzero(jsonStr,fileSize + 1); if(fread(jsonStr,fileSize,1,file) == 0) printf("文件读取失败"); printf("%sn",jsonStr); free(jsonStr); fclose(file); return ; }
extern cJSON *cJSON_Parse(const char *value); extern const char *cJSON_GetErrorPtr(void); extern char *cJSON_Print(cJSON *item);
将读取到的jsonStr字符串转为json数据,用cJSON结构体指针接收
// 将读取到的json字符串转换成json变量指针
cJSON *root = cJSON_Parse(jsonStr);
if (!root) {
const char *err = cJSON_GetErrorPtr();
printf("Error before: [%s]", err);
free((void *)err);
free(jsonStr);
return;
}
char *s = cJSON_Print(root);
printf("%sn",s);
free(s);
free(jsonStr);
3.直接进行解析
//cJSON结构体中的数据
// char *valuestring;
// int valueint;
// double valuedouble;
//判断类型
char *j_str = NULL;
double j_double = 0.0;
int j_int = 0;
bool j_bool = false;
//解析:"name":"client"
item = cJSON_GetObjectItem(root,"name");
if(item != NULL)
{
//判断是不是字符串
if(item->type == cJSON_String)
{
//获取字符串中的值
j_str = item->valuestring; //浅拷贝 j_str与item->valuestring指向的空间相同
printf("%sn",j_str);
j_str[0] = 'y';
printf("%sn",j_str); //ylient
printf("%sn",item->valuestring); //ylient
j_str = malloc(strlen(item->valuestring) + 1);
strcpy(j_str,item->valuestring); //深拷贝
j_str[0] = 'c';
printf("%sn",j_str); //client
printf("%sn",item->valuestring); //ylient
free(j_str);
}
}
// 类型判断
// #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_CreateNumber": 9999999
item = cJSON_GetObjectItem(root,"cJSON_CreateNumber");
if(item != NULL)
{
//判断是不是数字
if(item->type == cJSON_Number)
{
j_int = item->valueint;
printf("%dn",j_int); //9999999
}
}
// "cJSON_CreateNull": null
item = cJSON_GetObjectItem(root,"cJSON_CreateNull");
if(item != NULL)
{
if(item->type == cJSON_NULL)
{
j_str = cJSON_Print(item); //深拷贝 Free the char* when finished.
printf("%sn",j_str);
free(j_str);
}
}
// "cJSON_CreateTrue": true
item = cJSON_GetObjectItem(root,"cJSON_CreateTrue");
if(item != NULL)
{
if(item->type == cJSON_True)
{
j_str = cJSON_Print(item); //由于bool类型结构体中没有给出,所以使用字符串代替
printf("%sn",j_str);
free(j_str);
}
}
// "cJSON_CreateBool0": false
item = cJSON_GetObjectItem(root,"cJSON_CreateBool0");
if(item != NULL)
{
if(item->type == cJSON_False)
{
j_str = cJSON_Print(item);
printf("%sn",j_str);
free(j_str);
}
}
效果如下图:
4.解析数组解析代码:
item = cJSON_GetObjectItem(root,"color");
if(item != NULL)
{
if (item->type == cJSON_Array)
{
int size = cJSON_GetArraySize(item); //获取数组中元素个数
for(int i=0;i
cJSON *obj = cJSON_GetArrayItem(item,i);
if(obj != NULL && obj->type == cJSON_String)
{
printf("color : %sn",obj->valuestring);
}
}
}
}
5.解析{{},{}}
item = cJSON_GetObjectItem(root,"address");
if(item != NULL)
{
cJSON *val = NULL;
cJSON *south = cJSON_GetObjectItem(item,"南方");
cJSON *north = cJSON_GetObjectItem(item,"北方");
if(south != NULL)
{
val = cJSON_GetObjectItem(south,"city");
if(val != NULL && val->type == cJSON_String)
printf("%sn",val->valuestring);
val = cJSON_GetObjectItem(south,"street");
if(val != NULL && val->type == cJSON_String)
printf("%sn",val->valuestring);
}
if(north != NULL)
{
val = cJSON_GetObjectItem(north,"city");
if(val != NULL && val->type == cJSON_String)
printf("%sn",val->valuestring);
val = cJSON_GetObjectItem(north,"street");
if(val != NULL && val->type == cJSON_String)
printf("%sn",val->valuestring);
}
}
参考:
从零开始的 JSON 库教程
CC++ 使用cjson库 操作Json格式文件(创建、插入、解析、修改、删除)



