cJSON 原始碼分析

2021-10-06 06:19:10 字數 4290 閱讀 4062

在解決這三個問題之前,先介紹一下我所使用的原始碼分析工具:

gcc/g++:原始碼編譯

make:原始碼構建(需要編寫makefile)

gdb:原始碼除錯

json主要的值型別null,false,true,number(數字),string(字串),array(陣列)以及object(物件),其中字串用雙引號" "表示,陣列用表示,物件用{}表示,樣例如下所示,值得注意的是陣列或者物件是可以巢狀使用的。

}

對於json資料,cjson庫用了雙向鍊錶這兩種資料結構來構建,裡面的基本元素(鍵值對)稱作乙個結點,將上面的樣例資料用樹形結構表示,如圖1所示。

圖1 json樣例資料的樹形結構 

樹中的每乙個結點用結構體表示,對應cjson庫的原始碼如下,其中

typedef struct cjson  cjson;
好了,到這裡我們已經知道cjson庫是如何表示json格式的資料了,通過以下**就可以生成先前的json樣例資料,因此,我們只要弄懂了下列函式的原理,生成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_createobject()函式內部的執行過程,該函式通過呼叫cjson_new_item ()分配記憶體,建立空白結點,如果建立成功則標識該結點的型別為物件型別,也就是說該函式的作用是建立乙個物件結點。

cjson * cjson_createobject (void)

/* internal constructor. */

static cjson * cjson_new_item (void)

接著看cjson_additemtoobject函式,這裡涉及的**有點多,不過大家不要怕,我們一起來解讀這段**:該函式有3個形參,分別是物件父節點、子結點名字以及子結點,該函式要求子結點已經分配記憶體,如果子結點的名字已被賦值,則會被釋放再重新賦予指定的名字,在這一過程中,由於名字是通過指標傳入的,為了不影響原先這塊記憶體的值,所以子結點的名字值實際指向的是傳入值在記憶體中的乙份副本;到這裡也僅僅是修改了子結點的名字,最關鍵的一步是將物件父節點和子結點建立聯絡,該過程封裝在cjson_additemtoarray (object,item)函式中,其通過父節點的child欄位完成繫結,並將子結點插入鍊錶的表尾。

void cjson_additemtoobject (cjson * object, const char * string, cjson * item)

static char * cjson_strdup (const char * str)

/* add item to array/object. */

void cjson_additemtoarray (cjson * array, cjson * item)

else }

/* utility for array list handling. */

static void suffix_object (cjson * prev, cjson * item)

通過下面的原始碼得知,其餘各型別資料實際都是呼叫函式cjson_additemtoobject新增的,因此只要根據樣例資料的內容,分別呼叫對應的函式將子結點新增到物件父節點即可。

/* macros for creating things quickly. */

#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))

經過前兩步,我們已經知道了如何表示json資料以及生成json資料,接下來看看cjson庫是如何解析json資料的。**如下所示,通過呼叫cjson_parse函式返回json樹的根節點,其執行流程如圖2所示,原始的輸入json_text是存在字元陣列(char *)中的,在解析的時候利用指標逐字元判斷當前資料的型別,根據該型別進入相應的分支解析資料;接著只要呼叫cjson_getobjectitem就可以獲取指定名字的結點。

圖2 cjson_parse 函式執行流程

由於null,false,true型別的資料解析簡單,這裡主要介紹string、number、array、object的解析,原始碼就不貼了,可以在原始檔中找到對應函式來看。

至此,cjson庫的核心功能差不多這些了,其他的細節以及值得學習借鑑的技術有待日後琢磨總結,最後看一下cjson庫生成和解析json資料的效果。

generate json data: 

}json parse result:

name: jack ("bee") nimble

type: rect

width: 1920

height: 1080

interlace: 0

framerate: 24

c json原始碼分析

本文主要講述對於c json部分 api的作用 c下面的 json 字串格式 直接寫在程式裡面,是用來轉義 的 此處格式必須正確,否則後面解析會出問題 在c語言中 json 串說白了就是字串,用字元陣列儲存,在解析過程中將自己要解析的 json 串傳入cjson parse value 函式,即可 ...

C json原始碼呼叫

2,挑選需要的 檔案。3,通過codeblacks編譯器驗證原始碼的使用 2,挑選需要的 檔案 jsoncpp src 0.5.0 src lib json jsoncpp src 0.5.0 include json 複製這兩個資料夾下的所有檔案到同乙個資料夾下面,資料夾名字命名為json,如下所...

cJSON原始碼的使用說明

cjson是通訊方面乙個相容性比較好的乙個格式,具體的相關的格式如下 針對資源中的main函式來講解一下使用cjson原始碼的流程和相關的介面 組裝資料報 cjson pjsonroot null pjsonroot cjson createobject if null pjsonroot cjso...