<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一種cJSON與結構體互轉(zhuǎn)的方法

          共 5975字,需瀏覽 12分鐘

           ·

          2023-10-15 18:46

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

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


          前言

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

          思路

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

          實現(xiàn)

          CSON正是采用上面說到的思路,使用數(shù)據(jù)模型對結構體進行描述,然后基于cJSON,根據(jù)數(shù)據(jù)模型進行解析,將解析得到的數(shù)據(jù)直接寫入到對應的內(nèi)存區(qū)域,從而實現(xiàn)從json到結構體對象的映射。
          CSON最基本的數(shù)據(jù)模型定義如下:
          typedef struct cson_model
          {

              CsonType type;                      /**< 數(shù)據(jù)類型 */
              char *key;                          /**< 元素鍵值 */
              short offset;                       /**< 元素偏移 */
          } CsonModel;
          通過type描述結構體成員的數(shù)據(jù)類型,key描述該成員在json中對應的字段,offset描述該結構體成員在結構體中的偏移,CSON在解析json的時候,根據(jù)type調(diào)用相應的cJSON API并傳遞key作為參數(shù),得到解析出的數(shù)據(jù),然后根據(jù)offset將數(shù)據(jù)寫入到對應的內(nèi)存空間。
          比如說這樣一個結構體:
          struct project
          {

              int id;
              char *name;
          }
          該結構體包含兩個成員,對于成員id,我們使用數(shù)據(jù)模型對其進行描述
          {.type=CSON_TYPE_CHAR, key="id", offset=0}
          對于結構體的每個成員,都進行數(shù)據(jù)模型的定義,就可以得到一個完整的結構體數(shù)據(jù)模型,CSON會根據(jù)這個模型,進行解析。
          因為是通過直接寫內(nèi)存的方式,所以在寫不同類型的量到內(nèi)存中時,會多次用到強制轉(zhuǎn)型,導致CSON中賦值的代碼都類似于:
          *(int *)((int)obj + model[i].offset) = (int)csonDecodeNumber(json, model[i].key);
          當然,上面說到的數(shù)據(jù)模型,只適用于基本數(shù)據(jù)類型的數(shù)據(jù),對于子結構體,鏈表,數(shù)組等,需要對數(shù)據(jù)模型的定義進行擴充,有興趣的朋友可以直接閱讀CSON源碼。

          CSON使用實例

          聲明結構體:

          /** 項目結構體 */
          struct project
          {

              int id;
              char *name;
          };

          /** 倉庫結構體 */
          struct hub
          {

              int id;
              char *user;
              struct project *cson;
          };

          定義數(shù)據(jù)模型:

          對每一個需要使用cson的結構體,都需要定義相對應的數(shù)據(jù)模型
          /** 項目結構體數(shù)據(jù)模型 */
          CsonModel projectModel[] =
          {
              CSON_MODEL_OBJ(struct project),
              CSON_MODEL_INT(struct project, id),
              CSON_MODEL_STRING(struct project, name),
          };

          /** 倉庫結構體數(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(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);

              /** 釋放結構體對象 */
              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地址

          ?

          https://github.com/NevermindZZT/cson

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

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

               
               

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

               
               

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

          瀏覽 1779
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  无一区二区三区 | 国产毛片一卡二卡 | 黄色电影免费一级片 | 人妻-X88AⅤ | 国产无遮挡又黄又爽又 |