1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        一種cJSON與結(jié)構(gòu)體互轉(zhuǎn)的方法

        共 5975字,需瀏覽 12分鐘

         ·

        2023-10-15 18:46

           
           
            關(guān)注、星標(biāo)公眾號,直達(dá)精彩內(nèi)容
        來自:CSDN,作者:NevermindZZT

        鏈接:https://blog.csdn.net/qq_34245464/article/details/100168884


        前言

        json是目前最為流行的文本數(shù)據(jù)傳輸格式,特別是在網(wǎng)絡(luò)通信上廣泛應(yīng)用,隨著物聯(lián)網(wǎng)的興起,在嵌入式設(shè)備上,也需要開始使用json進(jìn)行數(shù)據(jù)傳輸,那么,如何快速簡潔地用C語言進(jìn)行json的序列化和反序列化呢?
        當(dāng)前,應(yīng)用最廣泛的C語言json解析庫當(dāng)屬cJSON,但是,使用cJSON讀json進(jìn)行序列化和反序列化,需要根據(jù)key一個一個進(jìn)行處理,會導(dǎo)致代碼冗余,邏輯性不強(qiáng),哪有沒有更好的方法呢?

        思路

        在Android平臺,一般會使用gson等工具解析json,這些工具將json直接映射成對象,在C語言上使用對象的概念,我們需要借助結(jié)構(gòu)體,然而,最大的問題在于,C語言沒有高級語言具有的反射機(jī)制,直接從json映射到結(jié)構(gòu)體對象幾乎是不可能的。
        怎么解決呢,既然C語言沒有反射機(jī)制,那么我們可以自己定義一套類似于反射的機(jī)制,這里我將其稱之為結(jié)構(gòu)體數(shù)據(jù)模型,在數(shù)據(jù)模型中,我們需要準(zhǔn)確地描述結(jié)構(gòu)體的特征,包括結(jié)構(gòu)體各成員的名稱,類型,在結(jié)構(gòu)體中的偏移。
        有了這些,我們可以在解析josn的時候,將解析得到的數(shù)據(jù)直接寫入到對應(yīng)的內(nèi)存里面去,或者是在序列化的時候,直接從對應(yīng)的內(nèi)存中讀取數(shù)據(jù),進(jìn)行處理。

        實(shí)現(xiàn)

        CSON正是采用上面說到的思路,使用數(shù)據(jù)模型對結(jié)構(gòu)體進(jìn)行描述,然后基于cJSON,根據(jù)數(shù)據(jù)模型進(jìn)行解析,將解析得到的數(shù)據(jù)直接寫入到對應(yīng)的內(nèi)存區(qū)域,從而實(shí)現(xiàn)從json到結(jié)構(gòu)體對象的映射。
        CSON最基本的數(shù)據(jù)模型定義如下:
        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ù)模型對其進(jìn)行描述
        {.type=CSON_TYPE_CHAR, key="id", offset=0}
        對于結(jié)構(gòu)體的每個成員,都進(jìn)行數(shù)據(jù)模型的定義,就可以得到一個完整的結(jié)構(gòu)體數(shù)據(jù)模型,CSON會根據(jù)這個模型,進(jìn)行解析。
        因?yàn)槭峭ㄟ^直接寫內(nèi)存的方式,所以在寫不同類型的量到內(nèi)存中時,會多次用到強(qiáng)制轉(zhuǎn)型,導(dǎo)致CSON中賦值的代碼都類似于:
        *(int *)((int)obj + model[i].offset) = (int)csonDecodeNumber(json, model[i].key);
        當(dāng)然,上面說到的數(shù)據(jù)模型,只適用于基本數(shù)據(jù)類型的數(shù)據(jù),對于子結(jié)構(gòu)體,鏈表,數(shù)組等,需要對數(shù)據(jù)模型的定義進(jìn)行擴(kuò)充,有興趣的朋友可以直接閱讀CSON源碼。

        CSON使用實(shí)例

        聲明結(jié)構(gòu)體:

        /** 項(xiàng)目結(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ù)模型
        /** 項(xiàng)目結(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進(jìn)行序列化和反序列化
        void csonDemo(void)
        {
            char *jsonDemo = "{\"id\": 1, \"user\": \"Letter\", \"cson\": {\"id\": 2, \"name\": \"cson\"}}";

            /** 解析json */
            struct hub *pHub = csonDecode(jsonDemohubModelsizeof(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);
        }

        運(yùn)行結(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

        ?
        版權(quán)聲明:本文來源網(wǎng)絡(luò),免費(fèi)傳達(dá)知識,版權(quán)歸原作者所有。如涉及作品版權(quán)問題,請聯(lián)系我進(jìn)行刪除。

        ????????????????  END  ???????????????

             
             

        關(guān)注我的微信公眾號,回復(fù)“加群”按規(guī)則加入技術(shù)交流群。

             
             

        點(diǎn)擊“閱讀原文”查看更多分享,歡迎點(diǎn)分享、收藏、點(diǎn)贊、在看。

        瀏覽 1779
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            国产精品人妻人伦a 片久 | AAA片视频 | 特级特黄A级高潮播放 | 亚洲国产伦理 | 日韩屄 | 91人人人 | 亚洲国产一级电影 | 无码18p| 人人操人人摸人人色 | 古言荒淫h女h |