不可不知的JSON處理庫(cJSON)

東小東發表於2020-06-06

ANSI C中的超輕量級JSON解析器

JSON(JavaScript物件表示法)是一種輕量級的資料交換格式。人類易於閱讀和書寫。機器很容易解析和生成。它基於JavaScript程式語言標準ECMA-262第三版(1999年12月)的子集 。JSON是一種完全獨立於語言的文字格式,但是使用C語言家族(包括C,C ++,C#,Java,JavaScript,Perl,Python等)的程式設計師熟悉的約定。這些屬性使JSON成為理想的資料交換語言。

cJSON旨在成為您可以完成工作的最簡單的解析器。它是資源只有一個C的標頭檔案和C檔案,所以方便移植。它可以為你各種需要的json字串處理,包括打包、解析、修改、刪除、新增等。在這裡將一探究竟。

在這裡將著重敘述json的打包和解析,更多處理玩法,見文章末尾連結。

開始cJSON

cJSON合併到您的專案

因為整個庫只有一個C檔案和一個標頭檔案,所以您只需複製cJSON.h並複製cJSON.c到專案源並開始使用它。

cJSON用ANSI C(C89)編寫,以便支援儘可能多的平臺和編譯器。

 

下載:

https://github.com/DaveGamble/cJSON/releases

 

Cjson結構體

/* The cJSON structure: */
typedef struct cJSON
{
    struct cJSON *next;
    struct cJSON *prev;
    struct cJSON *child;
    int type;
    char *valuestring;
    int valueint;
    double valuedouble;
    char *string;
} cJSON;

結構體項解析:

next 和prev :Cjson結構體作為一個雙向連表的環,可以通過 next 和prev 指標進行連表遍歷

child:可以是cJSON_Array、cJSON_Object型別資料

type:當前項的型別

valuestring:內容儲存,當型別是cJSON_String和cJSON_Raw

valueint:內容儲存,整型,可以是cJSON_False、cJSON_True資料

valuedouble:內容儲存,浮點型,當型別是cJSON_Number

string:鍵名

資料型別

l  cJSON_Invalid表示一個不包含任何值的無效專案。如果將專案設定為全零位元組,則將自動具有此型別。

l  cJSON_False表示一個false布林值。您也可以使用來檢查布林值cJSON_IsBool

l  cJSON_True表示一個true布林值。您也可以使用來檢查布林值cJSON_IsBool

l  cJSON_NULL表示一個null值

l  cJSON_Number 表示一個數字值。該值儲存為double in valuedouble和in valueint。如果數字超出整數範圍,INT_MAX或INT_MIN用於valueint

l  cJSON_String表示一個字串值。它以零終止字串的形式儲存在中valuestring

l  cJSON_Array表示一個陣列值。這是通過指向表示陣列中值child的cJSON專案的連結列表來實現的。使用next和將元素連結在一起prev,其中第一個元素具有prev.next == NULL和最後一個元素next == NULL

l  cJSON_Object 表示一個物件值。物件的儲存方式與陣列相同,唯一的區別是物件中的項將其鍵儲存在中string

l  cJSON_Raw表示以JSON字元儲存的零終止形式的任何JSON valuestring。例如,可以使用它來避免一遍又一遍地列印相同的靜態JSON以節省效能。解析時,cJSON永遠不會建立此型別。另請注意,cJSON不會檢查其是否為有效JSON。

型別

#define cJSON_Invalid (0)
#define cJSON_False  (1 << 0)
#define cJSON_True   (1 << 1)
#define cJSON_NULL   (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array  (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw    (1 << 7) /* raw json */

型別判斷

cJSON_IsInvalid(const cJSON * const item);
cJSON_IsFalse(const cJSON * const item);
cJSON_IsTrue(const cJSON * const item);
cJSON_IsBool(const cJSON * const item);
cJSON_IsNull(const cJSON * const item);
cJSON_IsNumber(const cJSON * const item);
cJSON_IsString(const cJSON * const item);
cJSON_IsArray(const cJSON * const item);
cJSON_IsObject(const cJSON * const item);
cJSON_IsRaw(const cJSON * const item);

注意

建立cjson物件後,處理完需要進行記憶體釋放:

如果是cjson裡的物件,請使用cJSON_Delete()

如果不是物件:cJSON_free()或free()

 

零字元

cJSON不支援包含零字元'\0'或的字串\u0000。對於當前的API,這是不可能的,因為字串以零結尾。

 

字元編碼

cJSON僅支援UTF-8編碼的輸入。但是在大多數情況下,它不會拒絕無效的UTF-8作為輸入,而只是將其原樣傳播。只要輸入不包含無效的UTF-8,輸出將始終是有效的UTF-8。

 

C標準

cJSON用ANSI C(或C89,C90)編寫。如果您的編譯器或C庫未遵循此標準,則不能保證正確的行為。

 

注意:ANSI C不是C ++,因此不應使用C ++編譯器進行編譯。您可以使用C編譯器對其進行編譯,然後將其與C ++程式碼連結。儘管可以使用C ++編譯器進行編譯,但是不能保證正確的行為。

 

浮點數字

double除IEEE754雙精度浮點數外,cJSON不正式支援任何實現。它可能仍然可以與其他實現一起使用,但是這些實現的錯誤將被視為無效。

 

目前,cJSON支援的浮點文字的最大長度為63個字元。

 

陣列和物件的深層巢狀

cJSON不支援巢狀太深的陣列和物件,因為這會導致堆疊溢位。為了防止這種CJSON_NESTING_LIMIT情況,預設情況下,cJSON將深度限制為1000,但是可以在編譯時進行更改。

格式化輸出

按標準的格式輸出json字串,輸出完後一定要記得釋放記憶體

 程式碼

 1 #include <stdio.h>
 2 #include "cJSON.h"
 3 #include "cJSON.c"
 4 void main(){
 5     //待解析字串 
 6     char *json_str="{\"key1\":\"dongxiaodong\",\"key2\":1998,\"key3\":55778}";
 7     
 8     //輸出原字串
 9     printf("原字串:%s\r\n",json_str); 
10 
11     //解析成json物件 
12     cJSON * json_obj = cJSON_Parse(json_str); 
13 
14     //格式輸出
15     char *json_print_str=NULL;
16     json_print_str=cJSON_Print(json_obj);
17     printf("\r\n輸出內容:\r\n\r\n%s\r\n",json_print_str);
18     
19     //釋放資源 
20     free(json_print_str);
21     
22     //釋放資源 
23     cJSON_Delete(json_obj);
24 }

json打包

cJSON_CreateObject函式可建立一個根資料項,在此之後就可以新增各種資料型別的子節點了,使用完成後需要通過cJSON_Delete()釋放記憶體。

建立一層級的json

 程式碼:

 1 #include <stdio.h>
 2 #include "cJSON.h"
 3 #include "cJSON.c"
 4 void main(){
 5     cJSON *root_obj = NULL;//根,json物件 
 6     char *out_str = NULL; //輸出結果 
 7     root_obj =cJSON_CreateObject();//建立 
 8      //新增一個字串,引數(根物件,鍵,值) 
 9     cJSON_AddStringToObject(root_obj, "key1", "dongxiaodong");
10     //新增一個整型,引數(根物件,鍵,值) 
11     cJSON_AddNumberToObject(root_obj, "key2",1998);
12     //新增一個浮點型,引數(根物件,鍵,值) 
13     cJSON_AddNumberToObject(root_obj, "key3",22.33);
14     //新增一個bool型別,引數(根物件,鍵,值) 
15     //bool值可以是0/1或false/true 
16     cJSON_AddBoolToObject(root_obj, "key4",0);
17     //將json物件打包成字串 
18     out_str = cJSON_PrintUnformatted(root_obj);
19     //銷燬json物件,釋放記憶體 
20     cJSON_Delete(root_obj); 
21     //輸出值:{"key1":"dongxiaodong","key2":1998,"key3":22.33,"key4":false} 
22     printf("%s",out_str);
23 }

型別建立函式還有:

cJSON_AddNullToObject(cJSON * const object, const char * const name);

cJSON_AddTrueToObject(cJSON * const object, const char * const name);

cJSON_AddFalseToObject(cJSON * const object, const char * const name);

cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);

cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);

cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);

cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);

cJSON_AddObjectToObject(cJSON * const object, const char * const name);

cJSON_AddArrayToObject(cJSON * const object, const char * const name);

建立多層級的json

 程式碼:

 1 #include <stdio.h>
 2 #include "cJSON.h"
 3 #include "cJSON.c"
 4 void main(){
 5     cJSON *root_obj = NULL;//根,json物件 
 6     cJSON *item_obj = NULL;//二級json物件 
 7     char *out_str = NULL; //輸出結果 
 8     
 9     root_obj =cJSON_CreateObject();//建立 
10      //新增一個字串,引數(根物件,鍵,值) 
11     cJSON_AddStringToObject(root_obj, "key1", "dongxiaodong");
12     //新增一個整型,引數(根物件,鍵,值) 
13     cJSON_AddNumberToObject(root_obj, "key2",1998);
14     
15     //建立一個子json物件
16     item_obj= cJSON_AddObjectToObject(root_obj,"myson"); 
17     //向孩子物件中新增內容
18     cJSON_AddStringToObject(item_obj, "sonkey1", "東小東"); 
19     cJSON_AddNumberToObject(item_obj, "sonkey2",2020);
20       
21     //將json物件打包成字串 
22     out_str = cJSON_PrintUnformatted(root_obj);
23     //銷燬json物件,釋放記憶體 
24     cJSON_Delete(root_obj); 
25     //輸出值:{"key1":"dongxiaodong","key2":1998,"myson":{"sonkey1":"東小東","sonkey2":2020}}
26     printf("%s",out_str);
27 }

建立多層json(陣列形式)

 

 程式碼

 1 #include <stdio.h>
 2 #include "cJSON.h"
 3 #include "cJSON.c"
 4 void main(){
 5     cJSON *root_obj = NULL;//根,json物件 
 6     cJSON *item_obj = NULL;//陣列物件 
 7     char *out_str = NULL; //輸出結果 
 8     
 9     root_obj =cJSON_CreateObject();//建立 
10      //新增一個字串,引數(根物件,鍵,值) 
11     cJSON_AddStringToObject(root_obj, "key1", "dongxiaodong");
12     //新增一個整型,引數(根物件,鍵,值) 
13     cJSON_AddNumberToObject(root_obj, "key2",1998);
14     
15     //建立一個子陣列物件 
16     item_obj= cJSON_AddArrayToObject(root_obj,"myson"); 
17     //向陣列物件中新增內容
18     cJSON_AddItemToArray(item_obj,cJSON_CreateTrue()); 
19     cJSON_AddItemToArray(item_obj,cJSON_CreateNumber(22));
20       
21     //將json物件打包成字串 
22     out_str = cJSON_PrintUnformatted(root_obj);
23     //銷燬json物件,釋放記憶體 
24     cJSON_Delete(root_obj); 
25     //輸出值:{"key1":"dongxiaodong","key2":1998,"myson":[true,22]}
26     printf("%s",out_str);
27 }

建立的物件還可以是下面這些

cJSON_CreateNull(void);

cJSON_CreateTrue(void);

cJSON_CreateFalse(void);

cJSON_CreateBool(cJSON_bool boolean);

cJSON_CreateNumber(double num);

cJSON_CreateString(const char *string);

cJSON_CreateRaw(const char *raw);

cJSON_CreateArray(void);

cJSON_CreateObject(void);

建立混合json

 程式碼

 1 #include <stdio.h>
 2 #include "cJSON.h"
 3 #include "cJSON.c"
 4 void main(){
 5     cJSON *root_obj = NULL;//根,json物件 
 6     cJSON *son_obj=NULL; 
 7     cJSON *item_obj = NULL;//陣列物件 
 8     char *out_str = NULL; //輸出結果 
 9     
10     //根物件 
11     root_obj =cJSON_CreateObject();//建立 
12     //新增一個字串,引數(根物件,鍵,值) 
13     cJSON_AddStringToObject(root_obj, "key1", "dongxiaodong");
14     //新增一個整型,引數(根物件,鍵,值) 
15     cJSON_AddNumberToObject(root_obj, "key2",1998);
16     
17     //建立一個子陣列物件 
18     item_obj= cJSON_AddArrayToObject(root_obj,"myson"); 
19     //向陣列物件中新增內容
20     cJSON_AddItemToArray(item_obj,cJSON_CreateTrue()); 
21     cJSON_AddItemToArray(item_obj,cJSON_CreateNumber(22));
22     
23     //子物件 
24     son_obj =cJSON_CreateObject();//建立 
25     //新增一個字串,引數(根物件,鍵,值) 
26     cJSON_AddStringToObject(son_obj, "son1", "dongxiaodong");
27     //新增一個整型,引數(根物件,鍵,值) 
28     cJSON_AddNumberToObject(son_obj, "son2",1998);
29     cJSON_AddItemToArray(item_obj,son_obj);
30     
31     //將json物件打包成字串 
32     out_str = cJSON_PrintUnformatted(root_obj);
33     //銷燬json物件,釋放記憶體 
34     cJSON_Delete(root_obj); 
35     //輸出值:{"key1":"dongxiaodong","key2":1998,"myson":[true,22,{"son1":"dongxiaodong","son2":1998}]}
36     printf("%s",out_str);
37 }

json解析

解析一層級的json

 

程式碼:

 1 #include <stdio.h>
 2 #include "cJSON.h"
 3 #include "cJSON.c"
 4 void main(){
 5     //待解析字串 
 6     char *json_str="{\"key1\":\"dongxiaodong\",\"key2\":1998,\"key3\":22.33,\"key4\":true}";
 7     //解析成json物件 
 8     cJSON * json_obj = cJSON_Parse(json_str); 
 9     
10     //項儲存 
11     cJSON *item=NULL;
12     
13     //輸出原字串
14     printf("原字串:%s\r\n",json_str); 
15     
16     //獲取string型別 
17     item=cJSON_GetObjectItem(json_obj,"key1");  
18     printf("\r\nkey1:%s\r\n",item->valuestring);
19     cJSON_Delete(item);//釋放資源 
20      
21     //獲取數字 
22     item=cJSON_GetObjectItem(json_obj,"key2");  
23     printf("\r\nkey2:%d\r\n",item->valueint);
24     cJSON_Delete(item);//釋放資源 
25     
26     //獲取數字 
27     item=cJSON_GetObjectItem(json_obj,"key3");  
28     printf("\r\nkey3:%f\r\n",item->valuedouble);
29     cJSON_Delete(item);//釋放資源 
30     
31     //獲取bool 
32     item=cJSON_GetObjectItem(json_obj,"key4");  
33     printf("\r\nkey4:%d\r\n",item->valueint);
34     cJSON_Delete(item);//釋放資源 
35     
36     //是否資源 
37     cJSON_Delete(json_obj);
38 }

解析多層級的json

 

程式碼

 1 #include <stdio.h>
 2 #include "cJSON.h"
 3 #include "cJSON.c"
 4 void main(){
 5     //待解析字串 
 6     char *json_str="{\"key1\":\"dongxiaodong\",\"key2\":1998,\"myson\":{\"sonkey1\":\"東小東\",\"sonkey2\":2020}}";
 7     //解析成json物件 
 8     cJSON * json_obj = cJSON_Parse(json_str); 
 9     
10     //項儲存 
11     cJSON *item=NULL;
12     //內部項儲存
13     cJSON * item_item=NULL; 
14     
15     //輸出原字串
16     printf("原字串:%s\r\n",json_str); 
17     
18     //獲取string型別 
19     item=cJSON_GetObjectItem(json_obj,"key1");  
20     printf("\r\nkey1:%s\r\n",item->valuestring);
21     cJSON_Delete(item);//釋放資源 
22      
23     //獲取數字 
24     item=cJSON_GetObjectItem(json_obj,"key2");  
25     printf("\r\nkey2:%d\r\n",item->valueint);
26     cJSON_Delete(item);//釋放資源 
27     
28     //子串
29     item=cJSON_GetObjectItem(json_obj,"myson");  
30     item_item=cJSON_GetObjectItem(item,"sonkey1"); 
31     printf("\r\nmyson(sonkey1):%s\r\n",item_item->valuestring);
32     cJSON_Delete(item_item);//釋放資源 
33     
34     item_item=cJSON_GetObjectItem(item,"sonkey2"); 
35     printf("\r\nmyson(sonkey2):%d\r\n",item_item->valueint);
36     cJSON_Delete(item_item);//釋放資源 
37     
38     cJSON_Delete(item);//釋放資源 
39     
40     //釋放資源 
41     cJSON_Delete(json_obj);
42 }

 解析多層json(陣列形式)

  

程式碼

 1 #include <stdio.h>
 2 #include "cJSON.h"
 3 #include "cJSON.c"
 4 void main(){
 5     //待解析字串 
 6     char *json_str="{\"key1\":\"dongxiaodong\",\"key2\":1998,\"myson\":[true,113]}";
 7     //解析成json物件 
 8     cJSON * json_obj = cJSON_Parse(json_str); 
 9     
10     //項儲存 
11     cJSON *item=NULL;
12     //內部項儲存
13     cJSON * item_item=NULL; 
14     
15     //輸出原字串
16     printf("原字串:%s\r\n",json_str); 
17     
18     //獲取string型別 
19     item=cJSON_GetObjectItem(json_obj,"key1");  
20     printf("\r\nkey1:%s\r\n",item->valuestring);
21     cJSON_Delete(item);//釋放資源 
22      
23     //獲取數字 
24     item=cJSON_GetObjectItem(json_obj,"key2");  
25     printf("\r\nkey2:%d\r\n",item->valueint);
26     cJSON_Delete(item);//釋放資源 
27     
28     //獲取子串 
29     item=cJSON_GetObjectItem(json_obj,"myson"); 
30     
31     //輸出陣列大小 
32     printf("\r\n陣列大小:%d\r\n",cJSON_GetArraySize(item));
33     
34     //輸出項1內容 
35     item_item=cJSON_GetArrayItem(item,0); 
36     printf("\r\nmyson(0):%d\r\n",item_item->valueint);
37     //cJSON_Delete(item_item);//釋放資源 
38     
39     //輸出項2內容 
40     item_item=cJSON_GetArrayItem(item,1);
41     printf("\r\nmyson(1):%d\r\n",item_item->valueint);
42     cJSON_Delete(item_item);//釋放資源 
43     
44     cJSON_Delete(item);//釋放資源 
45     
46     //釋放資源 
47     cJSON_Delete(json_obj);
48 }

  解析混合json

程式碼

 1 #include <stdio.h>
 2 #include "cJSON.h"
 3 #include "cJSON.c"
 4 void main(){
 5     //待解析字串 
 6     char *json_str="{\"key1\":\"dongxiaodong\",\"key2\":1998,\"myson\":[true,22,{\"son1\":\"dongxiaodong\",\"son2\":1998}]}";
 7     //解析成json物件 
 8     cJSON * json_obj = cJSON_Parse(json_str); 
 9     
10     //項儲存 
11     cJSON *item=NULL;
12     //內部項儲存
13     cJSON * item_item=NULL; 
14     
15     //輸出原字串
16     printf("原字串:%s\r\n",json_str); 
17     
18     //獲取string型別 
19     item=cJSON_GetObjectItem(json_obj,"key1");  
20     printf("\r\nkey1:%s\r\n",item->valuestring);
21     cJSON_Delete(item);//釋放資源 
22      
23     //獲取數字 
24     item=cJSON_GetObjectItem(json_obj,"key2");  
25     printf("\r\nkey2:%d\r\n",item->valueint);
26     cJSON_Delete(item);//釋放資源 
27     
28     //獲取子串 
29     item=cJSON_GetObjectItem(json_obj,"myson"); 
30     
31     //輸出陣列大小 
32     printf("\r\n陣列大小:%d\r\n",cJSON_GetArraySize(item));
33     
34     //輸出項1內容 
35     item_item=cJSON_GetArrayItem(item,0); 
36     printf("\r\nmyson(0):%d\r\n",item_item->valueint);
37     //cJSON_Delete(item_item);//釋放資源 
38     
39     //輸出項2內容 
40     item_item=cJSON_GetArrayItem(item,1);
41     printf("\r\nmyson(1):%d\r\n",item_item->valueint);
42     cJSON_Delete(item_item);//釋放資源 
43     
44     //項3內容
45     item_item=cJSON_GetArrayItem(item,2); 
46     cJSON *item_item_son=NULL;
47     
48     item_item_son =cJSON_GetObjectItem(item_item,"son1");  
49     printf("\r\nmyson(2)(son1):%s\r\n",item_item_son->valuestring);
50     cJSON_Delete(item_item_son);//釋放資源 
51     
52     item_item_son =cJSON_GetObjectItem(item_item,"son2");  
53     printf("\r\nmyson(2)(son2):%d\r\n",item_item_son->valueint);
54     cJSON_Delete(item_item_son);//釋放資源
55     cJSON_Delete(item_item);//釋放資源   
56     
57     cJSON_Delete(item);//釋放資源 
58     
59     //釋放資源 
60     cJSON_Delete(json_obj);
61 }

 


 參考:

https://blog.csdn.net/shizhe0123/article/details/94742514

https://blog.csdn.net/fengxinlinux/article/details/53121287

https://www.cnblogs.com/skullboyer/p/8152157.html

相關文章