<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          C/C++ 關(guān)于 cJson 庫的使用

          共 17676字,需瀏覽 36分鐘

           ·

          2021-09-08 10:16

          關(guān)于 Json 這種數(shù)據(jù)格式,在前面已經(jīng)做了詳細(xì)的介紹 Json 的格式和用途,在項(xiàng)目開發(fā)過程中我們需要針對(duì)不同的語言使用不同的庫對(duì) Json 格式的數(shù)據(jù)進(jìn)行解析,下面給大家介紹一個(gè)基于 C 語言的 Json 庫 – cJson。cJSON 是一個(gè)超輕巧,攜帶方便,單文件,簡(jiǎn)單的可以作為 ANSI-C 標(biāo)準(zhǔn)的 JSON 解析器。

          cJSON 是一個(gè)開源項(xiàng)目,github 下載地址:

          https://github.com/DaveGamble/cJSON

          cJSON,目前來說,主要的文件有兩個(gè),一個(gè) cJSON.c 一個(gè) cJSON.h。使用的時(shí)候,將頭文件 include 進(jìn)去即可。

          如果是在 Linux 操作系統(tǒng)中使用,編譯 到時(shí)候需要添加數(shù)學(xué)庫 libm.so,如下所示:

          gcc  *.c  cJSON.c  -lm

          1. cJSON 結(jié)構(gòu)體

          cJSON.h 中定義了一個(gè)非常重要的結(jié)構(gòu)體 cJSON,想要熟悉使用 cJSON 庫函數(shù)可從 cJSON 結(jié)構(gòu)體入手,cJSON 結(jié)構(gòu)體如下所示:

          typedef struct cJSON {  
               struct cJSON *next,*prev;   
               struct cJSON *child;   
               int type;   
               char *valuestring;        // value值是字符串類型
               int valueint;  
               double valuedouble;   
               char *string;             // 對(duì)象中的key
          } cJSON; 

          關(guān)于這個(gè)結(jié)構(gòu)體做如下幾點(diǎn)的說明:

          1. cJOSN 結(jié)構(gòu)體是一個(gè)雙向鏈表,并且可通過 child 指針訪問下一層。
          2. 結(jié)構(gòu)體成員 type 變量用于描述數(shù)據(jù)元素的類型(如果是鍵值對(duì)表示 value 值的類型),數(shù)據(jù)元素可以是字符串可以是整形,也可以是浮點(diǎn)型。
          • 如果是整形值的話可通過 valueint 將值取出
          • 如果是浮點(diǎn)型的話可通過 valuedouble 將值取出
          • 如果是字符串類型的話可通過 valuestring 將值取出
          1. 結(jié)構(gòu)體成員 string 表示鍵值對(duì)中鍵值的名稱。

          cJSON 作為 Json 格式的解析庫,其主要功能就是構(gòu)建和解析 Json 格式了,比如要發(fā)送數(shù)據(jù):用途就是發(fā)送端將要發(fā)送的數(shù)據(jù)以 json 形式封裝,然后發(fā)送,接收端收到此數(shù)據(jù)后,還是按 json 形式解析,就得到想要的數(shù)據(jù)了。

          2. cJson API

          Json 格式的數(shù)據(jù)無外乎有兩種 Json對(duì)象和 Json數(shù)組,創(chuàng)建的 Json 數(shù)據(jù)串可能是二者中 的一種,也可能是二者的組合,不管哪一種通過調(diào)用相關(guān)的 API 函數(shù)都可以輕松的做到這一點(diǎn)。

          2.1 數(shù)據(jù)的封裝

          cJSON.h 頭文件中可以看到一些函數(shù)聲明,通過調(diào)用這些創(chuàng)建函數(shù)就可以將 Json 支持的數(shù)據(jù)類型封裝為 cJSON 結(jié)構(gòu)體類型:

          // 空值類型
          extern cJSON *cJSON_CreateNull(void);
          // 布爾類型
          extern cJSON *cJSON_CreateTrue(void);
          extern cJSON *cJSON_CreateFalse(void);
          extern cJSON *cJSON_CreateBool(int b);
          // 數(shù)值類型
          extern cJSON *cJSON_CreateNumber(double num);
          // 字符串類型
          extern cJSON *cJSON_CreateString(const char *string);
          // json數(shù)組(創(chuàng)建空數(shù)組)
          extern cJSON *cJSON_CreateArray(void);
          // json對(duì)象(創(chuàng)建空對(duì)象)
          extern cJSON *cJSON_CreateObject(void);

          另外,cJson 庫中還給我我們提供了一些更為簡(jiǎn)便的操作函數(shù),在創(chuàng)建數(shù)組的同時(shí)還可以進(jìn)行初始化

          // 創(chuàng)建一個(gè)Json數(shù)組, 元素為整形
          extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
          // 創(chuàng)建一個(gè)Json數(shù)組, 元素為浮點(diǎn)
          extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
          extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
          // 創(chuàng)建一個(gè)Json數(shù)組, 元素為字符串類型
          extern cJSON *cJSON_CreateStringArray(const char **strings,int count);

          2.2 Json 對(duì)象操作

          當(dāng)?shù)玫揭粋€(gè) Json 對(duì)象之后,就可以往對(duì)象中添加鍵值對(duì)了,可以使用 cJSON_AddItemToObject()

          extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);

          在 cJSON 庫中節(jié)點(diǎn)的從屬關(guān)系是通過樹來維護(hù)的,每一層節(jié)點(diǎn)都是通過鏈表來維護(hù)的,這樣就能分析出該函數(shù)參數(shù)的含義:

          • object:要添加的鍵值對(duì)從屬于那個(gè)節(jié)點(diǎn)
          • string:添加的鍵值對(duì)的鍵值
          • item:添加的鍵值對(duì)的 value 值(需要先將其封裝為 cJSON 類型的結(jié)構(gòu)體)

          為了讓我的操作更加方便,cJson 庫還給我們提供了一些宏函數(shù),方便我們快速的往 Json 對(duì)象中添加鍵值對(duì)

          #define cJSON_AddNullToObject(object,name)      cJSON_AddItemToObject(object, name, cJSON_CreateNull())
          #define cJSON_AddTrueToObject(object,name)      cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
          #define cJSON_AddFalseToObject(object,name)     cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
          #define cJSON_AddBoolToObject(object,name,b)    cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
          #define cJSON_AddNumberToObject(object,name,n)  cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
          #define cJSON_AddStringToObject(object,name,s)  cJSON_AddItemToObject(object, name, cJSON_CreateString(s))

          我們還可以根據(jù) Json 對(duì)象中的鍵值取出相應(yīng)的 value 值,API 函數(shù)原型如下:

          extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);

          2.3 Json 數(shù)組操作

          添加數(shù)據(jù)到 Json 數(shù)組中(原始數(shù)據(jù)需要先轉(zhuǎn)換為 cJSON 結(jié)構(gòu)體類型)

          extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);

          得到 Json 數(shù)組中元素的個(gè)數(shù):

          extern int cJSON_GetArraySize(cJSON *array);

          得到 Json 數(shù)組中指定位置的原素,如果返回 NULL 表示取值失敗了。

          extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);

          2.4 序列化

          序列化就是將 Json 格式的數(shù)據(jù)轉(zhuǎn)換為字符串的過程,cJson 庫中給我們提供了 3 個(gè)轉(zhuǎn)換函數(shù),具體如下:

          第一個(gè)參數(shù) item 表示 Json 數(shù)據(jù)塊的根節(jié)點(diǎn)。

          extern char  *cJSON_Print(cJSON *item);
          extern char  *cJSON_PrintUnformatted(cJSON *item);
          extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt);
          • 調(diào)用 cJSON_Print() 函數(shù)我們可以得到一個(gè)帶格式的 Json 字符串(有換行,看起來更直觀)
          • 調(diào)用 cJSON_PrintUnformatted() 函數(shù)會(huì)得到一個(gè)沒有格式的 Json 字符串(沒有換行,所有的數(shù)據(jù)都在同一行)。
          • 調(diào)用 cJSON_PrintBuffered() 函數(shù)使用緩沖策略將 Json 實(shí)體轉(zhuǎn)換為字符串,參數(shù) prebuffer 是指定緩沖區(qū)的大小,參數(shù) fmt==0 表示未格式化,fmt==1 表示格式化。

          我們?cè)诰幋a過程中可以根據(jù)自己的實(shí)際需求調(diào)用相關(guān)的操作函數(shù)得到對(duì)應(yīng)格式的 Json 字符串。

          2.5 Json 字符串的解析

          如果我們得到了一個(gè) Json 格式的字符串,想要讀出里邊的數(shù)據(jù),就需要對(duì)這個(gè)字符串進(jìn)行解析,處理方式就是將字符串轉(zhuǎn)換為 cJSON 結(jié)構(gòu)體,然后再基于這個(gè)結(jié)構(gòu)體讀里邊的原始數(shù)據(jù),轉(zhuǎn)換函數(shù)的函數(shù)原型如下:

          extern cJSON *cJSON_Parse(const char *value);

          2.6 內(nèi)存釋放

          當(dāng)我們將數(shù)據(jù)封裝為 cJSON 結(jié)構(gòu)類型的節(jié)點(diǎn)之后都會(huì)得到一塊堆內(nèi)存,當(dāng)我們釋放某個(gè)節(jié)點(diǎn)的時(shí)候可以調(diào)用 cJson 庫提供的刪除函數(shù) cJSON_Delete(),函數(shù)原型如下:

          extern void   cJSON_Delete(cJSON *c);

          該函數(shù)的參數(shù)為要釋放的節(jié)點(diǎn)的地址,在此強(qiáng)調(diào)一點(diǎn):在進(jìn)行內(nèi)存地址釋放的時(shí)候,當(dāng)前節(jié)點(diǎn)以及其子節(jié)點(diǎn)都會(huì)被刪除。

          3. Json 數(shù)據(jù)的封裝

          3.1 Json 對(duì)象操作舉例

          創(chuàng)建一個(gè)對(duì)象,并向這個(gè)對(duì)象里添加字符串和整型鍵值:

          #include<stdio.h>
          #include<stdlib.h>
          #include<string.h>
          #include"cJSON.h"
           
          int main()
          {
              cJSON * root;
              cJSON *arry;

              root=cJSON_CreateObject();                     // 創(chuàng)建根數(shù)據(jù)對(duì)象
              cJSON_AddStringToObject(root,"name","luffy");  // 添加鍵值對(duì)
              cJSON_AddStringToObject(root,"sex","man");     // 添加鍵值對(duì)
              cJSON_AddNumberToObject(root,"age",19);        // 添加鍵值對(duì)

              char *out = cJSON_Print(root);   // 將json形式轉(zhuǎn)換成字符串
              printf("%s\n",out);

              // 釋放內(nèi)存  
              cJSON_Delete(root);  
              free(out);        
          }

          運(yùn)行結(jié)果

          {
           "name""luffy",
           "sex""man",
           "age": 19
          }

          若干說明:

          • cJSON_CreateObject 函數(shù)可創(chuàng)建一個(gè)根對(duì)象,返回的是一個(gè) cJSON 指針,在這個(gè)指針用完了以后,需要手動(dòng)調(diào)用 cJSON_Delete(root) 進(jìn)行內(nèi)存回收。
          • 函數(shù) cJSON_Print() 內(nèi)部封裝了 malloc 函數(shù),所以需要使用 free() 函數(shù)釋放被 out 占用的內(nèi)存空間。

          3.2 Json 數(shù)組操作舉例

          創(chuàng)建一個(gè)數(shù)組,并向數(shù)組添加一個(gè)字符串和一個(gè)數(shù)字

          int main(int argc, char **argv)
          {
              cJSON *root;
              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);
              }
              cJSON_Delete(root);
              return 0;
          }

          運(yùn)行結(jié)果:

          ["Hello world",10]

          3.3 Json 對(duì)象、數(shù)組嵌套使用

          對(duì)象里面包括一個(gè)數(shù)組,數(shù)組里面包括對(duì)象,對(duì)象里面再添加一個(gè)字符串和一個(gè)數(shù)字

          {
              "person":[{
                  "name":"luffy",
                  "age":19
              }]
          }

          示例代碼:

          int main(int argc, char **argv)
          {
              cJSON *root, *body, *list;
              // josn 對(duì)象 root
              root = cJSON_CreateObject();
              // root 添加鍵值對(duì) person:json數(shù)組A
              cJSON_AddItemToObject(root,"person", body = cJSON_CreateArray());
              // json數(shù)組A 添加Json對(duì)象B
              cJSON_AddItemToArray(body, list = cJSON_CreateObject());
              // 在json對(duì)象B中添加鍵值對(duì): "name":"luffy"
              cJSON_AddStringToObject(list,"name","luffy");
              // 在json對(duì)象B中添加鍵值對(duì): "age":19
              cJSON_AddNumberToObject(list,"age",19);
           
              // 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;
          }

          運(yùn)行結(jié)果:

          {"person":[{"name":"luffy","age":19}]}

          4. 解析 Json 字符串

          4.1 解析 Json 對(duì)象

          Json 字符串的解析流程和數(shù)據(jù)的封裝流程相反,假設(shè)我們有這樣一個(gè) Json 字符串(字符串中的雙引號(hào)需要通過轉(zhuǎn)義字符將其轉(zhuǎn)譯為普通字符):

          {\"name\":\"luffy\",\"sex\":\"man\",\"age\":19}

          示例代碼如下:

          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #include "cJSON.h"
           
          int main()
          {
              cJSON *json, *name, *sex, *age;
              char* out="{\"name\":\"luffy\",\"sex\":\"man\",\"age\":19}";
           
              json = cJSON_Parse(out); //解析成json形式
              name = cJSON_GetObjectItem(json, "name");  //獲取鍵值內(nèi)容
              sex = cJSON_GetObjectItem(json, "sex");
              age = cJSON_GetObjectItem(json, "age");
           
              printf("name:%s,sex:%s,age:%d\n", name->valuestring, sex->valuestring, age->valueint);
           
              cJSON_Delete(json);  //釋放內(nèi)存 
          }

          輸出的結(jié)果:

          name:luffy,sex:man,age:19

          如果是在嚴(yán)格的場(chǎng)所,應(yīng)該先判定每個(gè) item 的 type,然后再考慮去取值

          4.2 解析嵌套的 Json 對(duì)象

          加大一點(diǎn)難度,下面我們解析一個(gè)嵌套的 Json 對(duì)象,數(shù)據(jù)如下:

          {\"list\":{\"name\":\"luffy\",\"age\":19},\"other\":{\"name\":\"ace\"}}
          int main()
          {
              char *s = "{\"list\":{\"name\":\"luffy\",\"age\":19},\"other\":{\"name\":\"ace\"}}";
              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;
          }

          打印結(jié)果:

          list type is 6
          name type is 4
          name is luffy
          age type is 3
          age is 19
          list type is 6
          name type is 4
          name is ace

          4.3 解析 Json 數(shù)組

          如果我們遇到的 Json 字符串是一個(gè) Json 數(shù)組格式,處理方式和 Json 對(duì)象差不多,比如我們要解析如下字符串:

          {\"names\":[\"luffy\",\"robin\"]}

          int main(int argc, char **argv)
          {
              char *s = "{\"names\":[\"luffy\",\"robin\"]}";
              cJSON *root = cJSON_Parse(s);
              if(!root) 
              {
                  printf("get root faild !\n");
                  return -1;
              }
              cJSON *js_list = cJSON_GetObjectItem(root, "names");
              if(!js_list)
              {
                  printf("no list!\n");
                  return -1;
              }
              int array_size = cJSON_GetArraySize(js_list);
              printf("array size is %d\n",array_size);
              for(int i=0; i< array_size; i++) 
              {
                  cJSON *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;
          }

          4.4 解析嵌套的 Json 對(duì)象和數(shù)組

          對(duì)于 Json 字符串最復(fù)雜的個(gè)數(shù)莫過于 Json 對(duì)象和 Json 數(shù)組嵌套的形式,下面通過一個(gè)例子演示一下應(yīng)該如何解析,字符串格式如下:

          {\"list\":[{\"name\":\"luffy\",\"age\":19},{\"name\":\"sabo\",\"age\":21}]}

          在解析的時(shí)候,我們只需要按照從屬關(guān)系,一層層解析即可:

          • 根節(jié)點(diǎn)是一個(gè) Json 對(duì)象,基于根節(jié)點(diǎn)中的 key 值取出對(duì)應(yīng)的 value 值,得到一個(gè) Json 數(shù)組
          • 讀出 Json 數(shù)組的大小,遍歷里邊的各個(gè)元素,每個(gè)元素都是一個(gè) Json 對(duì)象
          • 將 Json 對(duì)象中的鍵值對(duì)根據(jù) key 值取出對(duì)應(yīng)的 value 值
          • 從取出的 Value 值中讀出實(shí)際類型對(duì)應(yīng)的數(shù)值 示例代碼如下:
          #include "cJSON.h"
          #include <stdio.h>
          #include <stdlib.h>

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

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

          文章鏈接:https://subingwen.cn/c/cjson%E4%BD%BF%E7%94%A8/

          瀏覽 80
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  爱搞亚洲 | 亚洲激情小说区 | 国产人人爽 | 三级片在线网站 | 国产一区二区大鸡巴操女女在线视频91 |