javascript
c语言解析json报文源码,GitHub - faycheng/cJSON: cJson源码和源码分析
cJSON官方文檔翻譯
項目預期目標
文檔翻譯
函數列表
項目架構
源碼注釋
解析流程
快速使用
###版權說明
Copyright (c) 2009 Dave Gamble
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
歡迎使用cJSON。
cJSON旨在成為一個可以應用在工作中的低門檻json解析器。該項目包含一個.c文件,和一個.h文件。
對JSON格式和結構的描述可以查看這個網站:http://www.json.org/
JSON是一種類似于XML的格式,不過更加輕量級。你能夠使用它去移動數據,存儲數據,或者僅僅用于描述項目的狀態。
那么,如何使用cJSON呢?
添加cJSON.c到你的項目中,并且把cJSON.h放置到你的項目頭文件的搜索路徑中。
例如,你可以使用下面命令編譯一個使用cJSON的小例子:(tests目錄下有相關文件)
gcc cJSON.c test.c -o test -lm
./test
作為一個庫,cJSON盡力完成它能夠完成的各種瑣碎工作。就像哲學具有兩面性一樣,你也能夠通過兩種方式使用cJSON:自動和手動。
接下來,讓我們快速地走一遍cJSON的使用流程。
我從這個網站獲取了一些JSON文件:http://www.json.org/fatfree.html
正是這個網站頁面激發我寫一個具有JSON哲學的cJSON解析器,簡單,低門檻,別出心裁。
這是一份JSON數據:
{
"name": "Jack (\"Bee\") Nimble",
"format": {
"type": "rect",
"width": 1920,
"height": 1080,
"interlace": false,
"frame rate": 24
}
}
假設你從一個文件,網站,或者一個神奇的精靈那里得到了這個JSON數據,你首先需要用一個char*指針指向它。然后你可以通過解析獲得一個cJSON結構體。
解析JSON的方式:
cJSON *root = cJSON_Parse(my_json_string);
cJSON是一個對象。由于我們使用C語言實現,而C語言中沒有對象的概念,所以我們使用結構體模擬對象。
接下來,獲取framerate節點的值。
cJSON *format = cJSON_GetObjectItem(root,"format");
int framerate = cJSON_GetObjectItem(format,"frame rate")->valueint;
改變framerate節點的值。
cJSON_GetObjectItem(format,"frame rate")->valueint=25;
對節點完成增刪改查之后并不意味著完成了一切,每次完成操作后,都需要刪除根節點,否則會出現內存泄露。
cJSON_Delete(root);
上述方式就是通過自動模式使用cJSON。當你使用自動模式時,你必須在你要解除對節點的引用前仔細檢查指針是否釋放。
接下來,將會演示如何使用代碼生成一個完整的JSON。
cJSON *root,*fmt;
root=cJSON_CreateObject();
cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));
cJSON_AddItemToObject(root, "format", fmt=cJSON_CreateObject());
cJSON_AddStringToObject(fmt,"type","rect");
cJSON_AddNumberToObject(fmt,"width",1920);
cJSON_AddNumberToObject(fmt,"height",1080);
cJSON_AddFalseToObject (fmt,"interlace");
cJSON_AddNumberToObject(fmt,"frame rate",24);
一般來說,我們都希望使用少量的代碼便完成大部分工作。所以,在cJSON中沒有復雜的,不必要的配置和使用。查看test.c,你就能發現這一點。(test文件夾中的JSON大部分來自于json.org,少部分來自于其他地方)
學會自動模式后,那么,手動模式是怎樣的呢?
要了解手動模式,必須要先了解一些關于cJSON的細節。讓我們一起分析cJSON如何去指代JSON數據。cJSON本身不能夠分辨對象中的數組,只能識別值類型。通常每一個cJSON節點都包含一個兒子節點,多個兄弟節點,節點自身的值和節點自身的名稱。
根節點包含:節點類型"Object",子節點"name"。
子節點包含:節點名稱"name",節點值"Jack ("Bee") Nimble",和兄弟節點"format"。
format節點包含:節點類型"Object",節點名稱"format",和子節點"type"。
type節點包含:節點類型"String",節點名稱"type",節點值"rect",兄弟節點"width"
width節點包含:節點類型"Number",節點名稱"width",節點值1920,兄弟節點"height"
height節點包含:節點類型"Number",節點名稱"height",節點值1080,兄弟節點"interlace"
interlace節點包含:節點類型"False",節點名稱"interlace",兄弟節點"frame rate"
frame rate節點包含:節點類型"Number",節點名稱"frame tate",節點值25。
這是cJSON結構體的具體代碼:
typedef struct cJSON {
struct cJSON *next,*prev;
struct cJSON *child;
int type;
char *valuestring;
int valueint;
double valuedouble;
char *string;
} cJSON;
cJSON默認所有值都為0,除非額外為其賦有意義的值。
next/prev是一個雙向鏈表中的兄弟。next指向鏈表中下一個兄弟節點,prev指向本節點前一個節點。
只有對象和數組有child節點,并且child節點是雙向鏈表的頭節點。child的prev一般為NULL,不指向任何節點,而next一般是有指向的。
雙向鏈表的最后一個兄弟節點的next是無指向的。
type取值如下:Null/True/False/Number/String/Array/Object。這些值類型都在cJSON.h中通過宏定義了。
Number類型節點有valueint和valuedouble。如果你想要整形值,讀取valueint,否則讀取valuedouble。
所有的節點都是一個鏈表,都具有string值。string表示節點的名稱。在上述例子中,name都是指string變量。你可以將string理解為JSON節點變量的名稱(節點的名稱)。
你能夠調用cJSON_Parse去得到一個解析后的cJSON節點,然后你能夠根據這個根節點遍歷整個節點樹。當你得到cJSON_Parse解析后的結果后,你也可以使用自己的詞法分析函數處理節點樹。如果你想要構建一個解析器的回調函數,下面的代碼是一個不錯的例子(這是一個很簡單的例子,只適用特定情況,事實上,但你真正使用自己的詞法分析時,會比較復雜)。
void parse_and_callback(cJSON *item,const char *prefix)
{
while (item)
{
char *newprefix=malloc(strlen(prefix)+strlen(item->name)+2);
sprintf(newprefix,"%s/%s",prefix,item->name);
int dorecurse=callback(newprefix, item->type, item);
if (item->child && dorecurse) parse_and_callback(item->child,newprefix);
item=item->next;
free(newprefix);
}
}
除此之外,你可能也想要迭代解析節點。
你能夠使用下列方式:
void parse_object(cJSON *item)
{
int i;
for (i=0;i
{
cJSON *subitem=cJSON_GetArrayItem(item,i);
// handle subitem.
}
}
或者,使用手工模式解析節點:
void parse_object(cJSON *item)
{
cJSON *subitem=item->child;
while (subitem)
{
// handle subitem
if (subitem->child) parse_object(subitem->child);
subitem=subitem->next;
}
}
這是一個很簡單的回調解析器。
This should cover most uses you'll find for parsing. The rest should be possible
這篇文章應該包含了大部分需要使用的查詢和解析操作。如果你還有所疑惑,那么可以閱讀項目源碼,該項目源碼并不復雜。
上述的示例代碼已經能夠完成構建解析JSON數據的需求。
當然,你也能夠用自己的函數去構建cJSON節點。如果你有一個解析處理方式,你能夠手動的去處理。
例如,你能夠用以下的方式構建一個數組對象:
cJSON *objects[24];
cJSON *Create_array_of_anything(cJSON **items,int num)
{
int i;cJSON *prev, *root=cJSON_CreateArray();
for (i=0;i<24;i++)
{
if (!i)root->child=objects[i];
elseprev->next=objects[i], objects[i]->prev=prev;
prev=objects[i];
}
return root;
}
當你使用cJSON_Print, 會返回JSON結構的字符串。
test.c文件中的代碼含有大量解析使用cJSON的例子,你可以通過閱讀test.c來詳細了解cJSON的使用。
總結
以上是生活随笔為你收集整理的c语言解析json报文源码,GitHub - faycheng/cJSON: cJson源码和源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 德语语言文学考研c1,2015-2016
- 下一篇: c语言测机器运行时间,C语言clock(