CSON CJSON,解析json數(shù)據(jù)更優(yōu)雅?
時間:2021-09-30 13:53:51
手機看文章
掃描二維碼
隨時隨地手機看文章
[導(dǎo)讀]關(guān)注「嵌入式大雜燴」,選擇「星標公眾號」一起進步!作者?|??NevermindZZT前言json是目前最為流行的文本數(shù)據(jù)傳輸格式,特別是在網(wǎng)絡(luò)通信上廣泛應(yīng)用,隨著物聯(lián)網(wǎng)的興起,在嵌入式設(shè)備上,也需要開始使用json進行數(shù)據(jù)傳輸,那么,如何快速簡潔地用C語言進行json的序列化和...
關(guān)注「嵌入式大雜燴」,選擇「星標公眾號」一起進步!
前言
json是目前最為流行的文本數(shù)據(jù)傳輸格式,特別是在網(wǎng)絡(luò)通信上廣泛應(yīng)用,隨著物聯(lián)網(wǎng)的興起,在嵌入式設(shè)備上,也需要開始使用json進行數(shù)據(jù)傳輸,那么,如何快速簡潔地用C語言進行json的序列化和反序列化呢?
思路
在Android平臺,一般會使用gson等工具解析json,這些工具將json直接映射成對象,在C語言上使用對象的概念,我們需要借助結(jié)構(gòu)體,然而,最大的問題在于,C語言沒有高級語言具有的反射機制,直接從json映射到結(jié)構(gòu)體對象幾乎是不可能的。
實現(xiàn)
CSON正是采用上面說到的思路,使用數(shù)據(jù)模型對結(jié)構(gòu)體進行描述,然后基于cJSON,根據(jù)數(shù)據(jù)模型進行解析,將解析得到的數(shù)據(jù)直接寫入到對應(yīng)的內(nèi)存區(qū)域,從而實現(xiàn)從json到結(jié)構(gòu)體對象的映射。
typedef struct cson_model
{
CsonType type; /**< 數(shù)據(jù)類型 */
char *key; /**< 元素鍵值 */
short offset; /**< 元素偏移 */
} CsonModel;
通過type描述結(jié)構(gòu)體成員的數(shù)據(jù)類型,key描述該成員在json中對應(yīng)的字段,offset描述該結(jié)構(gòu)體成員在結(jié)構(gòu)體中的偏移,CSON在解析json的時候,根據(jù)type調(diào)用相應(yīng)的cJSON API并傳遞key作為參數(shù),得到解析出的數(shù)據(jù),然后根據(jù)offset將數(shù)據(jù)寫入到對應(yīng)的內(nèi)存空間。
比如說這樣一個結(jié)構(gòu)體:
struct project
{
int id;
char *name;
}
該結(jié)構(gòu)體包含兩個成員,對于成員id,我們使用數(shù)據(jù)模型對其進行描述
{.type=CSON_TYPE_CHAR, key="id", offset=0}
對于結(jié)構(gòu)體的每個成員,都進行數(shù)據(jù)模型的定義,就可以得到一個完整的結(jié)構(gòu)體數(shù)據(jù)模型,CSON會根據(jù)這個模型,進行解析。
因為是通過直接寫內(nèi)存的方式,所以在寫不同類型的量到內(nèi)存中時,會多次用到強制轉(zhuǎn)型,導(dǎo)致CSON中賦值的代碼都類似于:
*(int *)((int)obj model[i].offset) = (int)csonDecodeNumber(json, model[i].key);
當然,上面說到的數(shù)據(jù)模型,只適用于基本數(shù)據(jù)類型的數(shù)據(jù),對于子結(jié)構(gòu)體,鏈表,數(shù)組等,需要對數(shù)據(jù)模型的定義進行擴充,有興趣的朋友可以直接閱讀CSON源碼。
CSON使用實例
聲明結(jié)構(gòu)體:
/** 項目結(jié)構(gòu)體 */
struct project
{
int id;
char *name;
};
/** 倉庫結(jié)構(gòu)體 */
struct hub
{
int id;
char *user;
struct project *cson;
};
定義數(shù)據(jù)模型:
對每一個需要使用cson的結(jié)構(gòu)體,都需要定義相對應(yīng)的數(shù)據(jù)模型
/** 項目結(jié)構(gòu)體數(shù)據(jù)模型 */
CsonModel projectModel[] =
{
CSON_MODEL_OBJ(struct project),
CSON_MODEL_INT(struct project, id),
CSON_MODEL_STRING(struct project, name),
};
/** 倉庫結(jié)構(gòu)體數(shù)據(jù)模型 */
CsonModel hubModel[] =
{
CSON_MODEL_OBJ(struct hub),
CSON_MODEL_INT(struct hub, id),
CSON_MODEL_STRING(struct hub, user),
CSON_MODEL_STRUCT(struct hub, cson, projectModel, sizeof(projectModel)/sizeof(CsonModel))
};
使用CSON解析:
只需要定義好數(shù)據(jù)模型,就可以使用CSON讀json進行序列化和反序列化
void csonDemo(void)
{
char *jsonDemo = "{\"id\": 1, \"user\": \"Letter\", \"cson\": {\"id\": 2, \"name\": \"cson\"}}";
/** 解析json */
struct hub *pHub = csonDecode(jsonDemo, hubModel, sizeof(hubModel)/sizeof(CsonModel));
printf("hub: id: %d, user: %s, project id: %d, project name: %s\r\n",
pHub->id, pHub->user, pHub->cson->id, pHub->cson->name);
/** 序列化對象 */
char *formatJson = csonEncodeFormatted(pHub, hubModel, sizeof(hubModel)/sizeof(CsonModel));
printf("format json: %s\r\n", formatJson);
/** 釋放結(jié)構(gòu)體對象 */
csonFree(pHub, hubModel, sizeof(hubModel)/sizeof(CsonModel));
/** 釋放序列化生成的json字符串 */
csonFreeJson(formatJson);
}
運行結(jié)果:
hub: id: 1, user: Letter, project id: 2, project name: cson
format json: {
"id": 1,
"user": "Letter",
"cson": {
"id": 2,
"name": "cson"
}
}
可以看到,無論是解析json,還是序列化結(jié)構(gòu)體到j(luò)son,在使用CSON的情況下,都只需要一行代碼就可以解決,同樣的操作,在使用原生cJSON的情況下,你可能需要多次判斷,解析元素。
CSON地址
?https://github.com/NevermindZZT/cson
?
來源:https://blog.csdn.net/qq_34245464/
本文來源網(wǎng)絡(luò),版權(quán)歸原作者所有。如涉及作品版權(quán)問題,請聯(lián)系我進行刪除。
往期推薦:
嵌入式大雜燴文章精選
嵌入式C/C 編程修養(yǎng)
通過實例分析來認識一下QP狀態(tài)機
嵌入式學習不知從哪入門?不妨從這些知識開始
分享一個適用于嵌入式的CPP開源項目