日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

cjson使用_LiteOS云端对接教程01-cJSON组件使用教程

發(fā)布時(shí)間:2025/3/19 javascript 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 cjson使用_LiteOS云端对接教程01-cJSON组件使用教程 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1. JSON與cJSON

JSON —— 輕量級(jí)的數(shù)據(jù)格式

JSON 全稱 JavaScript Object Notation,即 JS對(duì)象簡譜,是一種輕量級(jí)的數(shù)據(jù)格式。

它采用完全獨(dú)立于編程語言的文本格式來存儲(chǔ)和表示數(shù)據(jù),語法簡潔、層次結(jié)構(gòu)清晰,易于人閱讀和編寫,同時(shí)也易于機(jī)器解析和生成,有效的提升了網(wǎng)絡(luò)傳輸效率。

JSON語法規(guī)則

JSON對(duì)象是一個(gè)無序的"名稱/值"鍵值對(duì)的集合:

  • 以"{"開始,以"}"結(jié)束,允許嵌套使用;
  • 每個(gè)名稱和值成對(duì)出現(xiàn),名稱和值之間使用":"分隔;
  • 鍵值對(duì)之間用","分隔
  • 在這些字符前后允許存在無意義的空白符;

對(duì)于鍵值,可以有如下值:

  • 一個(gè)新的json對(duì)象
  • 數(shù)組:使用"["和"]"表示
  • 數(shù)字:直接表示,可以是整數(shù),也可以是浮點(diǎn)數(shù)
  • 字符串:使用引號(hào)"表示
  • 字面值:false、null、true中的一個(gè)(必須是小寫)

示例如下:

{"name": "mculover666","age": 22,"weight": 55.5"address":{"country": "China","zip-code": 111111},"skill": ["c", "Java", "Python"],"student": false }

LiteOS中的cJSON組件

cJSON是一個(gè)使用C語言編寫的JSON數(shù)據(jù)解析器,具有超輕便,可移植,單文件的特點(diǎn),使用MIT開源協(xié)議。

LiteOS中已經(jīng)移植了cJSON,作為一個(gè)組件使用,源碼在sdkIoT_LINK_1.0.0iot_linkcJSON中,其源碼文件只有兩個(gè):

  • cJSON.h
  • cJSON.c

使用的時(shí)候,只需要將這兩個(gè)文件復(fù)制到工程目錄,然后包含頭文件cJSON.h即可,如下:

#include "cJSON.h"

2. cJSON數(shù)據(jù)結(jié)構(gòu)和設(shè)計(jì)思想

cJSON的設(shè)計(jì)思想從其數(shù)據(jù)結(jié)構(gòu)上就能反映出來。

cJSON使用cJSON結(jié)構(gòu)體來表示一個(gè)JSON數(shù)據(jù),定義在cJSON.h中,源碼如下:

/* The cJSON structure: */ typedef struct cJSON {/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */struct cJSON *next;struct cJSON *prev;/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */struct cJSON *child;/* The type of the item, as above. */int type;/* The item's string, if type==cJSON_String and type == cJSON_Raw */char *valuestring;/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */int valueint;/* The item's number, if type==cJSON_Number */double valuedouble;/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */char *string; } cJSON;

cJSON的設(shè)計(jì)很巧妙。

首先,它不是將一整段JSON數(shù)據(jù)抽象出來,而是將其中的一條JSON數(shù)據(jù)抽象出來,也就是一個(gè)鍵值對(duì),用上面的結(jié)構(gòu)體 strcut cJSON 來表示,其中用來存放值的成員列表如下:

  • String:用于表示該鍵值對(duì)的名稱;
  • type:用于表示該鍵值對(duì)中值的類型;
  • valuestring:如果鍵值類型(type)是字符串,則將該指針指向鍵值;
  • valueint:如果鍵值類型(type)是整數(shù),則將該指針指向鍵值;
  • valuedouble:如果鍵值類型(type)是浮點(diǎn)數(shù),則將該指針指向鍵值;

其次,一段完整的JSON數(shù)據(jù)中由很多鍵值對(duì)組成,并且涉及到鍵值對(duì)的查找、刪除、添加,所以使用鏈表來存儲(chǔ)整段JSON數(shù)據(jù),如上面的代碼所示:

  • next指針:指向下一個(gè)鍵值對(duì)
  • prev指針指向上一個(gè)鍵值對(duì)

最后,因?yàn)镴SON數(shù)據(jù)支持嵌套,所以一個(gè)鍵值對(duì)的值會(huì)是一個(gè)新的JSON數(shù)據(jù)對(duì)象(一條新的鏈表),也有可能是一個(gè)數(shù)組,方便起見,在cJSON中,數(shù)組也表示為一個(gè)數(shù)組對(duì)象,用鏈表存儲(chǔ),所以:

在鍵值對(duì)結(jié)構(gòu)體中,當(dāng)該鍵值對(duì)的值是一個(gè)嵌套的JSON數(shù)據(jù)或者一個(gè)數(shù)組時(shí),由child指針指向該條新鏈表。

3. 開啟cJSON組件

在LiteOS中,cJSON組件默認(rèn)是未開啟的,使用宏定義CONFIG_JSON_ENABLE開啟。

開啟之后,LiteOS會(huì)自動(dòng)進(jìn)行初始化,并且使用cJSON的內(nèi)存鉤子將cJSON申請(qǐng)內(nèi)存的方式變?yōu)槭褂胦salmalloc申請(qǐng),自動(dòng)初始化代碼在`linkmain.c`文件中:

4. JSON數(shù)據(jù)封裝

封裝方法

封裝JSON數(shù)據(jù)的過程,其實(shí)就是創(chuàng)建鏈表和向鏈表中添加節(jié)點(diǎn)的過程。

首先來講述一下鏈表中的一些術(shù)語:

  • 頭指針:指向鏈表頭結(jié)點(diǎn)的指針;
  • 頭結(jié)點(diǎn):不存放有效數(shù)據(jù),方便鏈表操作;
  • 首節(jié)點(diǎn):第一個(gè)存放有效數(shù)據(jù)的節(jié)點(diǎn);
  • 尾節(jié)點(diǎn):最后一個(gè)存放有效數(shù)據(jù)的節(jié)點(diǎn);

明白了這幾個(gè)概念之后,我們開始講述創(chuàng)建一段完整的JSON數(shù)據(jù),即如何創(chuàng)建一條完整的鏈表。

  • ① 創(chuàng)建頭指針:
cJSON* cjson_test = NULL;
  • ② 創(chuàng)建頭結(jié)點(diǎn),并將頭指針指向頭結(jié)點(diǎn):
cjson_test = cJSON_CreateObject();
  • ③ 盡情的向鏈表中添加節(jié)點(diǎn):
cJSON_AddNullToObject(cJSON * const object, const char * const name);cJSON_AddTrueToObject(cJSON * const object, const char * const name);cJSON_AddFalseToObject(cJSON * const object, const char * const name);cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);cJSON_AddObjectToObject(cJSON * const object, const char * const name);cJSON_AddArrayToObject(cJSON * const object, const char * const name);

輸出JSON數(shù)據(jù)

上面講述,一段完整的JSON數(shù)據(jù)就是一條長長的鏈表,那么,如何打印出這段JSON數(shù)據(jù)呢?

cJSON提供了一個(gè)API,可以將整條鏈表中存放的JSON信息輸出到一個(gè)字符串中:

(char *) cJSON_Print(const cJSON *item);

使用的時(shí)候,只需要接收該函數(shù)返回的指針地址即可。

封裝數(shù)據(jù)和打印數(shù)據(jù)示例

單純的講述方法還不夠,下面用一個(gè)例子來說明,封裝出開頭給出的那段JSON數(shù)據(jù)。

首先基于HelloWorld工程,創(chuàng)建一個(gè)存放示例文件的文件夾cloud_test_demo,并新建一個(gè)實(shí)驗(yàn)文件cjson_print_demo.c,編寫如下代碼:

#include <osal.h> #include <stdio.h> #include <cJSON.h>static int cjson_print_demo_entry() {cJSON* cjson_test = NULL;cJSON* cjson_address = NULL;cJSON* cjson_skill = NULL;char* str = NULL;/* 創(chuàng)建一個(gè)JSON數(shù)據(jù)對(duì)象(鏈表頭結(jié)點(diǎn)) */cjson_test = cJSON_CreateObject();/* 添加一條字符串類型的JSON數(shù)據(jù)(添加一個(gè)鏈表節(jié)點(diǎn)) */cJSON_AddStringToObject(cjson_test, "name", "mculover666");/* 添加一條整數(shù)類型的JSON數(shù)據(jù)(添加一個(gè)鏈表節(jié)點(diǎn)) */cJSON_AddNumberToObject(cjson_test, "age", 22);/* 添加一條浮點(diǎn)類型的JSON數(shù)據(jù)(添加一個(gè)鏈表節(jié)點(diǎn)) */cJSON_AddNumberToObject(cjson_test, "weight", 55.5);/* 添加一個(gè)嵌套的JSON數(shù)據(jù)(添加一個(gè)鏈表節(jié)點(diǎn)) */cjson_address = cJSON_CreateObject();cJSON_AddStringToObject(cjson_address, "country", "China");cJSON_AddNumberToObject(cjson_address, "zip-code", 111111);cJSON_AddItemToObject(cjson_test, "address", cjson_address);/* 添加一個(gè)數(shù)組類型的JSON數(shù)據(jù)(添加一個(gè)鏈表節(jié)點(diǎn)) */cjson_skill = cJSON_CreateArray();cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "C" ));cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "Java" ));cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "Python" ));cJSON_AddItemToObject(cjson_test, "skill", cjson_skill);/* 添加一個(gè)值為 False 的布爾類型的JSON數(shù)據(jù)(添加一個(gè)鏈表節(jié)點(diǎn)) */cJSON_AddFalseToObject(cjson_test, "student");/* 打印JSON對(duì)象(整條鏈表)的所有數(shù)據(jù) */str = cJSON_Print(cjson_test);printf("%sn", str);/* 釋放整條鏈表內(nèi)存 */cJSON_Delete(cjson_test);return 0; }int standard_app_demo_main() {osal_task_create("cjson_print_demo",cjson_print_demo_entry,NULL,0x800,NULL,2);return 0; }

在user_demo.mk中配置文件路徑:

#example for cjson_print_demoifeq ($(CONFIG_USER_DEMO), "cjson_print_demo") user_demo_src = ${wildcard $(TOP_DIR)/targets/STM32L431_BearPi/Demos/cloud_test_demo/cjson_print_demo.c}endif

位置如下:

然后在.sdkconfig中開啟cJSON組件,并且選中該demo:

實(shí)驗(yàn)結(jié)果如圖:

5. cJSON數(shù)據(jù)解析

解析方法

解析JSON數(shù)據(jù)的過程,其實(shí)就是剝離一個(gè)一個(gè)鏈表節(jié)點(diǎn)(鍵值對(duì))的過程。

解析方法如下:

  • ① 創(chuàng)建鏈表頭指針:
cJSON* cjson_test = NULL;
  • ② 解析整段JSON數(shù)據(jù),并將鏈表頭結(jié)點(diǎn)地址返回,賦值給頭指針:

解析整段數(shù)據(jù)使用的API只有一個(gè):

(cJSON *) cJSON_Parse(const char *value);
  • ③ 根據(jù)鍵值對(duì)的名稱從鏈表中取出對(duì)應(yīng)的值,返回該鍵值對(duì)(鏈表節(jié)點(diǎn))的地址
(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
  • ④ 如果JSON數(shù)據(jù)的值是數(shù)組,使用下面的兩個(gè)API提取數(shù)據(jù):
(int) cJSON_GetArraySize(const cJSON *array); (cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);

解析示例

下面用一個(gè)例子來說明如何解析出開頭給出的那段JSON數(shù)據(jù)。

在存放示例文件的文件夾cloud_test_demo中,再新建一個(gè)實(shí)驗(yàn)文件cjson_parse_demo.c,編寫如下代碼:

#include <osal.h> #include <stdio.h> #include <cJSON.h>char *message = "{ "name":"mculover666", "age": 22, "weight": 55.5, "address": { "country": "China","zip-code": 111111}, "skill": ["c", "Java", "Python"],"student": false }";static int cjson_test1_demo_entry() {cJSON* cjson_test = NULL;cJSON* cjson_name = NULL;cJSON* cjson_age = NULL;cJSON* cjson_weight = NULL;cJSON* cjson_address = NULL;cJSON* cjson_address_country = NULL;cJSON* cjson_address_zipcode = NULL;cJSON* cjson_skill = NULL;cJSON* cjson_student = NULL;int skill_array_size = 0, i = 0;cJSON* cjson_skill_item = NULL;/* 解析整段JSO數(shù)據(jù) */cjson_test = cJSON_Parse(message);if(cjson_test == NULL){printf("parse fail.n");return -1;}/* 依次根據(jù)名稱提取JSON數(shù)據(jù)(鍵值對(duì)) */cjson_name = cJSON_GetObjectItem(cjson_test, "name");cjson_age = cJSON_GetObjectItem(cjson_test, "age");cjson_weight = cJSON_GetObjectItem(cjson_test, "weight");printf("name: %sn", cjson_name->valuestring);printf("age:%dn", cjson_age->valueint);printf("weight:%.1fn", cjson_weight->valuedouble);/* 解析嵌套json數(shù)據(jù) */cjson_address = cJSON_GetObjectItem(cjson_test, "address");cjson_address_country = cJSON_GetObjectItem(cjson_address, "country");cjson_address_zipcode = cJSON_GetObjectItem(cjson_address, "zip-code");printf("address-country:%snaddress-zipcode:%dn", cjson_address_country->valuestring, cjson_address_zipcode->valueint);/* 解析數(shù)組 */cjson_skill = cJSON_GetObjectItem(cjson_test, "skill");skill_array_size = cJSON_GetArraySize(cjson_skill);printf("skill:[");for(i = 0; i < skill_array_size; i++){cjson_skill_item = cJSON_GetArrayItem(cjson_skill, i);printf("%s,", cjson_skill_item->valuestring);}printf("b]n");/* 解析布爾型數(shù)據(jù) */cjson_student = cJSON_GetObjectItem(cjson_test, "student");if(cjson_student->valueint == 0){printf("student: falsen");}else{printf("student:errorn");}/* 釋放整條鏈表內(nèi)存 */cJSON_Delete(cjson_test);return 0; }int standard_app_demo_main() {osal_task_create("cjson_test1_demo",cjson_test1_demo_entry,NULL,0x800,NULL,2);return 0; }

在user_demo.mk中配置文件路徑:

#example for cjson_parse_demoifeq ($(CONFIG_USER_DEMO), "cjson_parse_demo") user_demo_src = ${wildcard $(TOP_DIR)/targets/STM32L431_BearPi/Demos/cloud_test_demo/cjson_parse_demo.c}endif

位置如下:

然后在.sdkconfig中開啟cJSON組件,并且選中該demo:

實(shí)驗(yàn)結(jié)果如圖:

注意事項(xiàng)

在本示例中,因?yàn)槲姨崆爸罃?shù)據(jù)的類型,比如字符型或者浮點(diǎn)型,所以我直接使用指針指向?qū)?yīng)的數(shù)據(jù)域提取,在實(shí)際使用時(shí),如果提前不確定數(shù)據(jù)類型,應(yīng)該先判斷type的值,確定數(shù)據(jù)類型,再從對(duì)應(yīng)的數(shù)據(jù)域中提取數(shù)據(jù)。

6. cJSON使用過程中的內(nèi)存問題

內(nèi)存及時(shí)釋放

cJSON的所有操作都是基于鏈表的,所以cJSON在使用過程中大量的使用malloc從堆中分配動(dòng)態(tài)內(nèi)存的,所以在使用完之后,應(yīng)當(dāng)及時(shí)調(diào)用下面的函數(shù),清空cJSON指針?biāo)赶虻膬?nèi)存,該函數(shù)也可用于刪除某一條數(shù)據(jù):

(void) cJSON_Delete(cJSON *item);注意:該函數(shù)刪除一條JSON數(shù)據(jù)時(shí),如果有嵌套,會(huì)連帶刪除。

內(nèi)存鉤子

cJSON在支持自定義malloc函數(shù)和free函數(shù),方法如下:

  • ① 使用cJSON_Hooks來連接自定義malloc函數(shù)和free函數(shù):
typedef struct cJSON_Hooks {/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */void *(CJSON_CDECL *malloc_fn)(size_t sz);void (CJSON_CDECL *free_fn)(void *ptr); } cJSON_Hooks;
  • ② 初始化鉤子cJSON_Hooks
(void) cJSON_InitHooks(cJSON_Hooks* hooks);

總結(jié)

以上是生活随笔為你收集整理的cjson使用_LiteOS云端对接教程01-cJSON组件使用教程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日韩欧美综合一区 | 国产伦理片在线观看 | 美美女高清毛片视频免费观看 | www.久久艹 | 成 人片 黄 色 大 片 | 哺乳期喷奶水丰满少妇 | 午夜免费小视频 | 国产三区视频 | 欧美日韩国产综合在线 | 国产欧美视频在线观看 | 色漫在线观看 | 男女超爽视频免费播放 | 欧美三级一区二区 | 国产精品久久久不卡 | 无遮挡无掩盖网站 | 激情宗合网 | 香蕉av在线| 成人国产精品久久久网站 | 都市乱淫 | 超碰在线观看免费 | 羞羞的软件 | 日日噜噜夜夜狠狠久久波多野 | 国产粉嫩在线 | aaaaa黄色片 天堂网在线观看 | 青青草手机在线观看 | 欧美精品一区二区性色a+v | 久热精品视频在线观看 | 国产欧美一区二区在线观看 | 操啊操| 伊人春色网 | 国产精品无码白浆高潮 | 亚洲奶水xxxx哺乳期 | 久久成人a| 在线观看h网站 | 国产又爽又黄又嫩又猛又粗 | 51成人 | 一区二区伦理片 | 国产欧美综合一区 | 99免费看| 亚洲最大免费视频 | 免费人成在线 | 欧美性生活在线视频 | 黄色一毛片 | 五月天丁香社区 | 夜夜嗨av禁果av粉嫩avhd | 一区二区三区有限公司 | 日韩1024| 影音av资源| 一区二区三区四区免费视频 | 少妇熟女一区 | 午夜av影视 | 亚洲精品在线播放视频 | 青娱乐在线视频免费观看 | 久久久久一区二区三区四区 | 欧美三级黄 | 美国性生活大片 | 少妇精品无码一区二区三区 | 欧美国产乱视频 | 日本一区二区视频 | 欧美aaa级 | 激情偷乱人成视频在线观看 | 日批视频免费观看 | 亚洲乱码精品 | 欧美综合在线观看 | 亚洲国产精品一区二区久久hs | 黄色动漫软件 | 色窝窝无码一区二区三区 | 欧美一性一交 | 24小时日本在线www免费的 | 国产美女被遭强高潮免费网站 | 特色特色大片在线 | yy6080午夜| 在线观看黄色动漫 | 国产精成人品免费观看 | 亚洲小视频在线 | 68日本xxxxxⅹxxx22 | 日韩不卡免费 | 日本三级日本三级日本三级极 | 亚洲色图少妇 | 九九热色 | 国产午夜精品无码 | 韩国黄色视屏 | 就去色av | 亚洲高清av| 色妹子综合 | 瑟瑟网站在线观看 | 麻豆剧场 | 亚洲精品在线不卡 | 噼里啪啦动漫 | 无套内谢少妇高潮免费 | 婷婷啪啪 | 精品一区二区成人免费视频 | 人妻丰满熟妇岳av无码区hd | 成人另类小说 | 日韩中文字幕一区二区 | 欧洲日韩一区二区三区 | 国产视频在线看 | 麻豆影音先锋 | 女人天堂av|