www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > C語(yǔ)言與CPP編程
[導(dǎo)讀]關(guān)于Json這種數(shù)據(jù)格式,在前面已經(jīng)做了詳細(xì)的介紹?Json的格式和用途,在項(xiàng)目開(kāi)發(fā)過(guò)程中我們需要針對(duì)不同的語(yǔ)言使用不同的庫(kù)對(duì)Json格式的數(shù)據(jù)進(jìn)行解析,下面給大家介紹一個(gè)基于C語(yǔ)言的Json庫(kù)–cJson。cJSON是一個(gè)超輕巧,攜帶方便,單文件,簡(jiǎn)單的可以作為ANSI-C標(biāo)準(zhǔn)...

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

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

https://github.com/DaveGamble/cJSON

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

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

gcc??*.c??cJSON.c??-lm

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

cJSON.h 中定義了一個(gè)非常重要的結(jié)構(gòu)體 cJSON,想要熟悉使用 cJSON 庫(kù)函數(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)的說(shuō)明:

  1. cJOSN 結(jié)構(gòu)體是一個(gè)雙向鏈表,并且可通過(guò) child 指針訪問(wèn)下一層。
  2. 結(jié)構(gòu)體成員 type 變量用于描述數(shù)據(jù)元素的類型(如果是鍵值對(duì)表示 value 值的類型),數(shù)據(jù)元素可以是字符串可以是整形,也可以是浮點(diǎn)型。
  • 如果是整形值的話可通過(guò) valueint 將值取出
  • 如果是浮點(diǎn)型的話可通過(guò) valuedouble 將值取出
  • 如果是字符串類型的話可通過(guò) valuestring 將值取出
  1. 結(jié)構(gòu)體成員 string 表示鍵值對(duì)中鍵值的名稱。
cJSON 作為 Json 格式的解析庫(kù),其主要功能就是構(gòu)建和解析 Json 格式了,比如要發(fā)送數(shù)據(jù):用途就是發(fā)送端將要發(fā)送的數(shù)據(jù)以 json 形式封裝,然后發(fā)送,接收端收到此數(shù)據(jù)后,還是按 json 形式解析,就得到想要的數(shù)據(jù)了。

2. cJson API

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

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

cJSON.h 頭文件中可以看到一些函數(shù)聲明,通過(guò)調(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 庫(kù)中還給我我們提供了一些更為簡(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 庫(kù)中節(jié)點(diǎn)的從屬關(guān)系是通過(guò)樹(shù)來(lái)維護(hù)的,每一層節(jié)點(diǎn)都是通過(guò)鏈表來(lái)維護(hù)的,這樣就能分析出該函數(shù)參數(shù)的含義:

  • object:要添加的鍵值對(duì)從屬于那個(gè)節(jié)點(diǎn)
  • string:添加的鍵值對(duì)的鍵值
  • item:添加的鍵值對(duì)的 value 值(需要先將其封裝為 cJSON 類型的結(jié)構(gòu)體)
為了讓我的操作更加方便,cJson 庫(kù)還給我們提供了一些宏函數(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)換為字符串的過(guò)程,cJson 庫(kù)中給我們提供了 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 字符串(有換行,看起來(lái)更直觀)
  • 調(diào)用 cJSON_PrintUnformatted() 函數(shù)會(huì)得到一個(gè)沒(méi)有格式的 Json 字符串(沒(méi)有換行,所有的數(shù)據(jù)都在同一行)。
  • 調(diào)用 cJSON_PrintBuffered() 函數(shù)使用緩沖策略將 Json 實(shí)體轉(zhuǎn)換為字符串,參數(shù) prebuffer 是指定緩沖區(qū)的大小,參數(shù) fmt==0 表示未格式化,fmt==1 表示格式化。
我們?cè)诰幋a過(guò)程中可以根據(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 庫(kù)提供的刪除函數(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
#include
#include
#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
}
若干說(shuō)明:

  • 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)需要通過(guò)轉(zhuǎn)義字符將其轉(zhuǎn)譯為普通字符):

{\"name\":\"luffy\",\"sex\":\"man\",\"age\":19}
示例代碼如下:

#include?
#include?
#include?
#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????{
????????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ù)莫過(guò)于 Json 對(duì)象和 Json 數(shù)組嵌套的形式,下面通過(guò)一個(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?
#include?

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????{
????????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使用/

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉
關(guān)閉