cJSON的使用方法

首先,要介紹一下什麼是json格式。linux

一.JSON格式簡述json


JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式。易於人閱讀和編寫,同時也易於機器解析和生成。它基於JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一個子集。 JSON採用徹底獨立於語言的文本格式,可是也使用了相似於C語言家族的習慣(包括C, C++, C#, Java, JavaScript, Perl, Python等)。這些特性使JSON成爲理想的數據交換語言。(來自「開源中國」資料)。數組

cJSON從名字可知,整個項目都是以極標準的C來寫的,意思說,能夠跨各類平臺使用了。cJSON是一個超輕巧,攜帶方便,單文件,簡單的能夠做爲ANSI-C標準的JSON解析器。函數

cJSON 開源項目位置:點擊打開連接
更加詳細的解釋和示例請查看 http://www.json.org/ 主頁。.net

cJSON,目前來講,就只有兩個文件,一個cJSON.c 一個cJSON.h文件。使用的時候,本身建立好一個main.c文件後,將頭文件include進去。
若是是在linux pc上,請使用如下命令進行編譯:
gcc *.c cJSON.c -lm指針

記得編譯時末尾連接libm庫。orm


二.JSON結構體
熟悉使用cJSON庫函數可從cJSON結構體入手,cJSON結構體以下所示:
typedef struct cJSON {
struct cJSON *next,*prev;
struct cJSON *child;
int type;
char *valuestring;
int valueint;
double valuedouble;
char *string;
} cJSON; 對象

 

幾點說明blog

1.cJOSN結構體爲一個雙向列表,並可經過child指針訪問下一層。
2.type變量決定數據項類型(鍵的類型),數據項能夠是字符串能夠是整形,也能夠是浮點型。若是是整形值的話可從valueint,若是是浮點型的話可從valuedouble取出,以此類推。
3.string可理解爲節點的名稱,綜合此處的第2點可理解爲「鍵」的名稱。繼承

cJSON做爲Json格式的解析庫,其主要功能無非就是構建和解析Json格式了,用途就是一端將要發送的數據已cjson形式封裝,而後發送,另外一端收到此數據後,仍是按cjson形式解析,就獲得想要的數據了。

三.封裝成json形式
接下來直接經過幾個例子代碼,一一解析。
   
第一,建立json數據串。這數據串,多是對象,也多是數組,也多是它們的各類組合,其中再加上一些鍵值對。有一點要先說明:它們的組合,符合父子繼承格式--這也是json數據串的特色。
<1>建立一個對象,並向這個對象裏添加字符串和整型鍵值:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"cJSON.h"

int main()
{
cJSON * usr;
cJSON *arry;

usr=cJSON_CreateObject(); //建立根數據對象
cJSON_AddStringToObject(usr,"name","fengxin"); //加入鍵值,加字符串
cJSON_AddStringToObject(usr,"passwd","123");
cJSON_AddNumberToObject(usr,"num",1); //加整數

char *out = cJSON_Print(usr); //將json形式打印成正常字符串形式
printf("%s\n",out);

// 釋放內存
cJSON_Delete(usr);
free(out);


}

 


運行結果:
{
"name": "fengxin",
"passwd": "123",
"num": 1
}

若干說明

1. cJSON_CreateObject函數可建立一個根數據項,以後即可向該根數據項中添加string或int等內容,返回的是一個 cJSON的指針,注意,在這個指針用完了之後,須要手工調用 cJSON_Delete(root); 進行內存回收。
2. cJSON_AddNumberToObject向節點中添加子節點,例如此處添加name節點,節點值爲字符串"fengxin"
3. 須要注意的是  json 格式的數據,雖然也是一個字符串的樣子,但這個時候仍是沒法當成普通的字符串進行使用,須要調用 cJSON_PrintUnformatted(root) 或者 cJSON_Print(root);來將json對象轉換成普通的字符串,而且都是以該json對象的根爲基點。兩個API的區別便是:一個是沒有格式的:也就是轉換出的字符串中間不會有"\n" "\t"之類的東西存在,而cJSON_Print(root);打印出來是人看起來很舒服的格式。
4. 由於函數內部封裝有malloc函數,因此使用free函數釋放被out佔用的內存空間

<2> 建立一個數組,並向數組添加一個字符串和一個數字:
int create_js(void)
{
cJSON *root, *js_body;
root = cJSON_CreateArray();
cJSON_AddItemToArray(root, cJSON_CreateString("Hello world"));
cJSON_AddItemToArray(root, cJSON_CreateNumber(10));
{
// char *s = cJSON_Print(root);
char *s = cJSON_PrintUnformatted(root);
if(s){
printf(" %s \n",s);
free(s);
}
}
if(root)
cJSON_Delete(root);

return 0;

}

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

 

運行結果:
["Hello world",10]

<3> 對象裏面包括一個數組,數組裏麪包括對象,對象裏面再添加一個字符串和一個數字:
int create_js(void)
{
cJSON *root, *js_body, *js_list;
root = cJSON_CreateObject();
cJSON_AddItemToObject(root,"body", js_body = cJSON_CreateArray());
cJSON_AddItemToArray(js_body, js_list = cJSON_CreateObject());
cJSON_AddStringToObject(js_list,"name","fengxin");
cJSON_AddNumberToObject(js_list,"status",100);

{
// char *s = cJSON_Print(root);
char *s = cJSON_PrintUnformatted(root);
if(s){
printf(" %s \n",s);
free(s);
}
}
if(root)
cJSON_Delete(root);

return 0;
}

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


運行結果:
{"body":[{"name":"fengxin","status":100}]}

<4>其餘組合就依次類推,只要搞清楚父子關係便可。隨便嵌套隨便玩。再也不貼了。


四.解析json獲得數據
解析數據包的過程和組裝數據包的過程相反
處理流程:

1, 先將普通的json串處理成json對象,也就是所謂的建立json root的過程,只有一行代碼便可:

cJSON *root;
root = cJSON_Parse(js_string);

2,開始拿關鍵字,但若是關鍵字還有父層或者祖層,那就須要先從父層開拿,所謂剝洋蔥是也!

先說沒有父層的:

out={\"name\":\"fengxin\",\"passwd\":\"123\",\"num\":1}


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"cJSON.h"

int main()
{
cJSON *json,*json_name,*json_passwd,*json_num;
char* out="{\"name\":\"fengxin\",\"passwd\":\"123\",\"num\":1}";

json = cJSON_Parse(out); //解析成json形式
json_name = cJSON_GetObjectItem( json , "name" ); //獲取鍵值內容
json_passwd = cJSON_GetObjectItem( json , "passwd" );
json_num = cJSON_GetObjectItem( json , "num" );

printf("name:%s,passwd:%s,num:%d\n",json_name->valuestring,json_passwd->valuestring,json_num->valueint);

cJSON_Delete(json); //釋放內存
free(out);



}

 


顯示結果:
name:fengxin,passwd:123,num:1


須要注意的是: 上面的type 已經在cJSON.h裏面定義好了,有本身的意義。若是是在嚴格的場所,應該先斷定該 item的type,而後再考慮去拿值。

而若是有父層的話,無非就是接着向下拿就是了


3.處理這串數據:
out={\"list\":{\"name\":\"xiao hong\",\"age\":10},\"other\":{\"name\":\"hua hua\"}}

char *s = "{\"list\":{\"name\":\"xiao hong\",\"age\":10},\"other\":{\"name\":\"hua hua\"}}";
cJSON *root = cJSON_Parse(s);
if(!root) {
printf("get root faild !\n");
return -1;
}

cJSON *js_list = cJSON_GetObjectItem(root, "list");
if(!js_list) {
printf("no list!\n");
return -1;
}
printf("list type is %d\n",js_list->type);

cJSON *name = cJSON_GetObjectItem(js_list, "name");
if(!name) {
printf("No name !\n");
return -1;
}
printf("name type is %d\n",name->type);
printf("name is %s\n",name->valuestring);

cJSON *age = cJSON_GetObjectItem(js_list, "age");
if(!age) {
printf("no age!\n");
return -1;
}
printf("age type is %d\n", age->type);
printf("age is %d\n",age->valueint);

cJSON *js_other = cJSON_GetObjectItem(root, "other");
if(!js_other) {
printf("no list!\n");
return -1;
}
printf("list type is %d\n",js_other->type);

cJSON *js_name = cJSON_GetObjectItem(js_other, "name");
if(!js_name) {
printf("No name !\n");
return -1;
}
printf("name type is %d\n",js_name->type);
printf("name is %s\n",js_name->valuestring);

if(root)
cJSON_Delete(root);
return 0;


打印結果:
list type is 6
name type is 4
name is xiao hong
age type is 3
age is 10
list type is 6
name type is 4
name is hua hua


所謂子子孫孫無窮盡也,按照上面那個方法推下去便可。

4.json 裏數組怎麼取?
{\"list\":[\"name1\",\"name2\"]}

int main(int argc, char **argv)
{
char *s = "{\"list\":[\"name1\",\"name2\"]}";
cJSON *root = cJSON_Parse(s);
if(!root) {
printf("get root faild !\n");
return -1;
}
cJSON *js_list = cJSON_GetObjectItem(root, "list");
if(!js_list){
printf("no list!\n");
return -1;
}
int array_size = cJSON_GetArraySize(js_list);
printf("array size is %d\n",array_size);
int i = 0;
cJSON *item;
for(i=0; i< array_size; i++) {
item = cJSON_GetArrayItem(js_list, i);
printf("item type is %d\n",item->type);
printf("%s\n",item->valuestring);
}

if(root)
cJSON_Delete(root);
return 0;
}


5.若是json數組裏面又搞了對象怎麼辦? 

不怕搞對象,就怕這樣搞對象? 無他,就是稍微複雜了一點,全是體力活兒:

<1> 既然是數組裏面,那確定要先測量數組的大小,而後根據大小循環拿;

<2> 拿到一個數組項,而後把這個項先轉化成普通的json字符串,也就是 char *s 能接受的。

<3>再次將這個json字符串,轉化成一個json對象

<4> 按照拿普通對象中的東西那樣開幹就好了。

 

{\"list\":[{\"name\":\"xiao hong\",\"age\":10},{\"name\":\"hua hua\",\"age\":11}]}

list 是一個數組,數組裏面有兩個對象,那麼代碼以下

int main(int argc, char **argv){char *s = "{\"list\":[{\"name\":\"xiao hong\",\"age\":10},{\"name\":\"hua hua\",\"age\":11}]}";cJSON *root = cJSON_Parse(s);if(!root) { printf("get root faild !\n"); return -1;}cJSON *js_list = cJSON_GetObjectItem(root, "list");if(!js_list){ printf("no list!\n"); return -1;}int array_size = cJSON_GetArraySize(js_list);printf("array size is %d\n",array_size);int i = 0;cJSON *item,*it, *js_name, *js_age;char *p = NULL;for(i=0; i< array_size; i++) { item = cJSON_GetArrayItem(js_list, i); if(!item) { //TODO... } p = cJSON_PrintUnformatted(item); it = cJSON_Parse(p); if(!it) continue ; js_name = cJSON_GetObjectItem(it, "name"); printf("name is %s\n",js_name->valuestring); js_age = cJSON_GetObjectItem(it, "age"); printf("age is %d\n",js_age->valueint); } if(root) cJSON_Delete(root); return 0;}

相關文章
相關標籤/搜索