博客專欄

        EEPW首頁 > 博客 > 發現了一個很棒的開源項目CSON

        發現了一個很棒的開源項目CSON

        發布人:xiaomaidashu 時間:2023-12-01 來源:工程師 發布文章
        前言

        json是目前最為流行的文本數據傳輸格式,特別是在網絡通信上廣泛應用,隨著物聯網的興起,在嵌入式設備上,也需要開始使用json進行數據傳輸,那么,如何快速簡潔地用C語言進行json的序列化和反序列化呢

        當前,應用最廣泛的C語言json解析庫當屬cJSON,但是,使用cJSON讀json進行序列化和反序列化,需要根據key一個一個進行處理,會導致代碼冗余,邏輯性不強,哪有沒有更好的方法呢

        思路

        在Android平臺,一般會使用gson等工具解析json,這些工具將json直接映射成對象,在C語言上使用對象的概念,我們需要借助結構體,然而,最大的問題在于,C語言沒有高級語言具有的反射機制,直接從json映射到結構體對象幾乎是不可能的

        怎么解決呢,既然C語言沒有反射機制,那么我們可以自己定義一套類似于反射的機制,這里我將其稱之為結構體數據模型,在數據模型中,我們需要準確地描述結構體的特征,包括結構體各成員的名稱,類型,在結構體中的偏移,有了這些,我們可以在解析josn的時候,將解析得到的數據直接寫入到對應的內存里面去,或者是在序列化的時候,直接從對應的內存中讀取數據,進行處理

        實現

        CSON正是采用上面說到的思路,使用數據模型對結構體進行描述,然后基于cJSON,根據數據模型進行解析,將解析得到的數據直接寫入到對應的內存區域,從而實現從json到結構體對象的映射

        CSON最基本的數據模型定義如下:

        typedef struct cson_model
        {
            CsonType type;                      /**< 數據類型 */
            char *key;                          /**< 元素鍵值 */
            short offset;                       /**< 元素偏移 */
        } CsonModel;

        通過type描述結構體成員的數據類型,key描述該成員在json中對應的字段,offset描述該結構體成員在結構體中的偏移,CSON在解析json的時候,根據type調用相應的cJSON API并傳遞key作為參數,得到解析出的數據,然后根據offset將數據寫入到對應的內存空間

        比如說這樣一個結構體:

        struct project
        {
            int id;
            char *name;
        }

        該結構體包含兩個成員,對于成員id,我們使用數據模型對其進行描述{.type=CSON_TYPE_CHAR, key="id", offset=0},對于結構體的每個成員,都進行數據模型的定義,就可以得到一個完整的結構體數據模型,CSON會根據這個模型,進行解析

        因為是通過直接寫內存的方式,所以在寫不同類型的量到內存中時,會多次用到強制轉型,導致CSON中賦值的代碼都類似于*(int *)((int)obj + model[i].offset) = (int)csonDecodeNumber(json, model[i].key);

        當然,上面說到的數據模型,只適用于基本數據類型的數據,對于子結構體,鏈表,數組等,需要對數據模型的定義進行擴充,有興趣的朋友可以直接閱讀CSON源碼

        CSON使用實例聲明結構體
        /** 項目結構體 */
        struct project
        {
            int id;
            char *name;
        };
        
        /** 倉庫結構體 */
        struct hub
        {
            int id;
            char *user;
            struct project *cson;
        };
        定義數據模型

        對每一個需要使用cson的結構體,都需要定義相對應的數據模型

        /** 項目結構體數據模型 */
        CsonModel projectModel[] =
        {
            CSON_MODEL_OBJ(struct project),
            CSON_MODEL_INT(struct project, id),
            CSON_MODEL_STRING(struct project, name),
        };
        
        /** 倉庫結構體數據模型 */
        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解析

        只需要定義好數據模型,就可以使用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: %srn",
                pHub->id, pHub->user, pHub->cson->id, pHub->cson->name);
        
            /** 序列化對象 */
            char *formatJson = csonEncodeFormatted(pHub, hubModel, sizeof(hubModel)/sizeof(CsonModel));
            printf("format json: %srn", formatJson);
        
            /** 釋放結構體對象 */
            csonFree(pHub, hubModel, sizeof(hubModel)/sizeof(CsonModel));
        
            /** 釋放序列化生成的json字符串 */
            csonFreeJson(formatJson);
        }

        運行結果:

        hub: id: 1, user: Letter, project id: 2, project name: cson
        format json: {
                "id":   1,
                "user": "Letter",
                "cson": {
                        "id":   2,
                        "name": "cson"
                }
        }

        可以看到,無論是解析json,還是序列化結構體到json,在使用CSON的情況下,都只需要一行代碼就可以解決,同樣的操作,在使用原生cJSON的情況下,你可能需要多次判斷,解析元素

        項目地址

        CSON項目已經發布到Githubhttps://github.com/NevermindZZT/cson


        *博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。



        關鍵詞: CSON

        技術專區

        關閉
        主站蜘蛛池模板: 马公市| 黑水县| 全南县| 萨迦县| 岑溪市| 章丘市| 卓尼县| 周宁县| 丹凤县| 富川| 翁源县| 房产| 蒲城县| 乌鲁木齐市| 井陉县| 宜州市| 贵德县| 南投市| 彰化市| 平陆县| 新乐市| 吴堡县| 灵山县| 邵阳县| 安吉县| 车致| 富平县| 扶沟县| 新沂市| 保定市| 镇坪县| 德清县| 从江县| 富阳市| 奎屯市| 丰城市| 古蔺县| 阿克| 洞头县| 息烽县| 延庆县|