cJSON庫學習——C語言結構體與JSON互相轉換


跟着這兩個教程學習的:

https://www.cnblogs.com/young525/p/5873783.html

https://www.jianshu.com/p/59eb2bd1aeea

cJSON是一個公開庫,一共兩個文件,分別是是cJSON.c和cJSON.h,鏈接如下:

​​​​​​https://github.com/DaveGamble/cJSON

顧名思義,這個庫的主要目的就是往C語言中引入JSON的數據結構,下面給一段示例的代碼片段:

#include <stdio.h>
#include "cJSON.h"

int main() {
    //JSON本質上就是鍵值對,所以JSON在C語言中的表現形式就是鍵值對組成的字符串
    //字符串需要加雙引號,所有的鍵默認為字符串
    //一共定義了7種類型,可以查看cJSON.h中的cJSON Types這一行了解
    //以下為兩種JSON字符串的常見形式
    //普通JSON
    /*{ "json" : { 
                    "id":1, 
                    "nodeId":11, 
                    "deviceId":111, 
                    "deviceName":"aaa", 
                    "ieee":"01212", 
                    "ep":"1111", 
                    "type":"bbb" 
                  }
       }
    //加入了數組的JSON
      {  "id":[1,2,3,4,5], 
         "nodeId":11, 
         "deviceId":111, 
         "deviceName":"aaa"
       }
    */
    char* json1 = "{ \"json\" : { \"id\":1, \"nodeId\":11, \"deviceId\":111, \"deviceName\":\"aaa\", \"ieee\":\"01212\", \"ep\":\"1111\", \"type\":\"bbb\" }}";
    char* json2 = "{\"id\":[1,2,3,4,5], \"nodeId\":11, \"deviceId\":111, \"deviceName\":\"aaa\"}";
    cJSON* root;
    cJSON* format;
    cJSON* array;
    int value_int;
    int array_len;
    int i = 0;
    char* value_string;

    //解析json1
    //通過cJSON_Parse解析接收到的字符串,再通過cJSON_GetObjectItem獲取指定鍵的值,最后釋放該JSON結點的內存
    root = cJSON_Parse(json1);
    format = cJSON_GetObjectItem(root, "json");
    value_int = cJSON_GetObjectItem(format, "nodeId")->valueint;
    value_string = cJSON_GetObjectItem(format, "ieee")->valuestring;
    printf("%d\n", value_int);
    printf("%s\n", value_string);
    cJSON_Delete(root);

    //解析json2
    //添加了數組解析
    root = cJSON_Parse(json2);
    //數組解析
    array = cJSON_GetObjectItem(root, "id");//獲取數組的根節點
    value_int = cJSON_GetArraySize(array);//獲取數組長度
    printf("數組長度為:%d\n", value_int);
    //循環打印數組的內容
    for (i = 0; i < value_int; i++) {
        value_int = cJSON_GetArrayItem(array, i)->valueint;//獲取數組下標為i的數據,以int形式解析
        printf("第%d個元素為:%d\n",i+1,value_int);
    }
    value_string = cJSON_GetObjectItem(root, "deviceName")->valuestring;
    printf("%s\n", value_string);
    cJSON_Delete(root);

    return 0;
}

運行結果:

 

該代碼展示了​如何將一段以字符串形式表示的JSON串轉換為cJSON的結構並進行解析,接下來是如何通過代碼創建cJSON結構體:

#include <stdio.h>
#include "cJSON.h"


int main() {
    //通過cJSON_CreateObject創建根節點,通過cJSON_CreateArray創建數組
    //通過cJSON_AddItemToObject向一個節點添加元素,通過cJSON_AddItemToArray向數組添加元素
    cJSON* pRoot = cJSON_CreateObject();
    cJSON* pArray = cJSON_CreateArray();
    cJSON_AddItemToObject(pRoot, "students_info", pArray);

    cJSON* pItem = cJSON_CreateObject();
    cJSON_AddStringToObject(pItem, "name", "chenzhongjing");
    cJSON_AddStringToObject(pItem, "sex", "male");
    cJSON_AddNumberToObject(pItem, "age", 28);
    cJSON_AddItemToArray(pArray, pItem);

    pItem = cJSON_CreateObject();
    cJSON_AddStringToObject(pItem, "name", "fengxuan");
    cJSON_AddStringToObject(pItem, "sex", "male");
    cJSON_AddNumberToObject(pItem, "age", 24);
    cJSON_AddItemToArray(pArray, pItem);

    pItem = cJSON_CreateObject();
    cJSON_AddStringToObject(pItem, "name", "tuhui");
    cJSON_AddStringToObject(pItem, "sex", "male");
    cJSON_AddNumberToObject(pItem, "age", 22);
    cJSON_AddItemToArray(pArray, pItem);

    char* szJSON = cJSON_Print(pRoot);//通過cJSON_Print獲取cJSON結構體的字符串形式(注:存在\n\t)
    printf(szJSON);
    cJSON_Delete(pRoot);

    free(szJSON);
    return 0;
}

運行結果:

 

要注意的是產生的字符串中存在較多的\n與\t,如果不需要的話需要后期進行處理。

 

通過這兩段代碼,就可以借助cJSON庫來實現字符串與cJSON結構體的互相轉換。C語言結構體與JSON可以通過cJSON結構體來進行中轉,從而實現之間的轉換。以下為一個范例:

#include <stdio.h>
#include "cJSON.h"

typedef struct _c_struct_t{
    unsigned char a;
    unsigned short b;
    unsigned int c;
    unsigned long long d;
    float e;
}c_struct_t;

int main() {
    //創建JSON串:{"uint_8":8,"uint_16":16,"uint_32":32,"uint_64":64,"float":6.13141516}
    //其中float格式故意越界初始化
    c_struct_t testStruct1 = { 255,16,32,64,6.13141516 };
    c_struct_t testStruct2 = { 0 };
    cJSON* pRoot = cJSON_CreateObject();
    cJSON_AddNumberToObject(pRoot, "uint_8", testStruct1.a);
    cJSON_AddNumberToObject(pRoot, "uint_16", testStruct1.b);
    cJSON_AddNumberToObject(pRoot, "uint_32", testStruct1.c);
    cJSON_AddNumberToObject(pRoot, "uint_64", testStruct1.d);
    cJSON_AddNumberToObject(pRoot, "float", testStruct1.e);
    char* szJSON = cJSON_Print(pRoot);//通過cJSON_Print獲取cJSON結構體的字符串形式(注:存在\n\t)
    printf(szJSON);
    printf("\n");

    cJSON* root = cJSON_Parse(szJSON);
    testStruct2.a = cJSON_GetObjectItem(root, "uint_8")->valueint;
    testStruct2.b = cJSON_GetObjectItem(root, "uint_16")->valueint;
    testStruct2.c = cJSON_GetObjectItem(root, "uint_32")->valueint;
    testStruct2.d = cJSON_GetObjectItem(root, "uint_64")->valueint;
    testStruct2.e = cJSON_GetObjectItem(root, "float")->valuedouble;

    printf("%u\n%u\n%u\n%llu\n%f\n", testStruct2.a, testStruct2.b, testStruct2.c, testStruct2.d, testStruct2.e);

    return 0;
}

運行結果:

 

 可以看到float格式存儲的數據從6.13141516變成了這么一長串的數字,實際上在賦值后數值為6.13141537。這就是單精度的存儲范圍問題,以及單精度雙精度轉換的問題。在CJSON結構體中存儲數值時時以int格式存儲的,所以會產生這樣的問題。而在轉換為結構體中的float時,由於精度問題,只保留到小數點后第6位。

代碼中可以看到無論cJSON結構體的解析還是封裝都是挨個書寫的,這主要還是因為c語言中沒有反射機制,自己寫反射機制有點難。所以目前以我的水平只能寫成這樣,一種結構體一種轉換函數。

 

以上。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM