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