物聯網數據解析實戰:掌握CJSON庫核心函數,精準處理JSON數據
CJSON庫是一個輕量級的JSON解析庫,專為C語言設計,適用于嵌入式系統和物聯網應用。它提供了簡單易用的API,使得開發者能夠輕松地解析和生成JSON數據。在本教程中,我們將深入探討CJSON庫的核心函數,并學習如何使用它們來處理物聯網數據。
CJSON庫簡介
CJSON是一個用于解析和生成JSON數據的C語言庫。它由Lloyd Hilaiel編寫,旨在提供簡單、快速、高效的JSON處理能力。CJSON庫的核心函數包括解析JSON字符串、生成JSON字符串、遍歷JSON對象等,這些函數使得開發者能夠輕松地處理JSON數據,滿足物聯網應用的各種需求。
希望這篇博客能夠幫助到大家。點點關注,不迷路哦!
墨小羽ovo個人主頁
json和cJSON的區別
JSON(JavaScript Object Notation)是一種輕量級的數據交換格式。JSON數據通常以字符串的形式表示,例如:
{"name": "John","age": 30,"city": "New York"
}
而CJSON是一個用于解析和生成JSON數據的C語言庫。它提供了簡單易用的API,使得開發者能夠輕松地處理JSON數據。例如,使用CJSON庫可以解析上述JSON字符串,并獲取其中的"name"、"age"和"city"字段的值。
CJSON庫的安裝和使用
1.CJSON庫的安裝和使用非常簡單。你可以從CJSON的官方網站(https://github.com/DaveGamble/cJSON) 下載源代碼。
2.只需要CJSON.c和CJSON…h兩個文件,復制粘貼到我的keil代碼中即可。
CJSON庫的解析函數
-
cJSON_Parse
函數原型:cJSON *cJSON_Parse(const char *value);
功能描述:將JSON格式的字符串解析為cJSON結構體。
使用場景:當您從網絡、文件或其他來源接收到JSON格式的字符串時,可以使用此函數將其解析為C語言可操作的cJSON結構體。
參數說明:value:JSON格式的字符串。
返回值:解析成功返回指向cJSON結構體的指針,解析失敗返回NULL。
示例代碼:
char *json_str = "{\"name\":\"John\",\"age\":30,\"city\":\"New York\"}";cJSON *json = cJSON_Parse(json_str);if (json == NULL) {printf("Error parsing JSON\n");return 1;}//打印下這個json的值 printf("%s\n", cJSON_Print(json)); ```//運行結果 ```bash {"name": "John","age": 30,"city": "New York" }
-
cJSON_GetObjectItem
函數原型:cJSON *cJSON_GetObjectItem(cJSON *object, const char *string);
功能描述:從cJSON結構體中獲取指定字段的值。
使用場景:當您需要獲取JSON對象中某個字段的值時,可以使用此函數。
參數說明:object:指向cJSON結構體的指針。string:要獲取的字段名。
返回值:返回指向cJSON結構體的指針,如果字段不存在則返回NULL。
示例代碼:
cJSON *name = cJSON_GetObjectItem(json, "name");printf("Name: %s\n", name->valuestring);
運行結果
Name: John
`
2.嵌套的json數據,解析下這個json中的gps中的lon字段
#include <stdio.h>#include "cJSON.h"int main() {}char *json_str = "{\"id\":\"1702723082863\",\"version\":\"1.0\",\"params\":{\"gps\":{\"value\":{\"lon\":112,\"lat\":23}},\"humi\":{\"value\":31},\"lat\":{\"value\":23},\"led_state\":{\"value\":1},\"lng\":{\"value\":23},\"temp\":{\"value\":13}}}";cJSON *json = cJSON_Parse(json_str);if (json == NULL) {printf("Error parsing JSON\n");return 1;}cJSON *params = cJSON_GetObjectItem(json, "params");cJSON *gps = cJSON_GetObjectItem(params, "gps");cJSON *value = cJSON_GetObjectItem(gps, "value");cJSON *lon = cJSON_GetObjectItem(value, "lon");printf("lon: %d\n", lon->valueint);cJSON_Delete(json);return 0;}
運行結果
lon: 112
3.cJSON_Delete
函數原型:void cJSON_Delete(cJSON *item);功能描述:釋放cJSON結構體所占用的內存。使用場景:當您不再需要使用cJSON結構體時,應該調用此函數釋放內存。參數說明:item:指向cJSON結構體的指針。返回值:無。示例代碼:
cJSON_Delete(json);
4.cJSON_Print
函數原型:char *cJSON_Print(const cJSON *item);功能描述:將cJSON結構體轉換為JSON格式的字符串。使用場景:當您需要將cJSON結構體轉換為JSON格式的字符串時,可以使用此函數。參數說明:item:指向cJSON結構體的指針。返回值:返回指向JSON格式的字符串的指針。示例代碼:
char *json_str = cJSON_Print(json);printf("%s\n", json_str);
運行結果:
{"name":"John","age":30,"city":"New York"}
CJSON庫的示例代碼
#include <stdio.h>
#include "cJSON.h"int main() {char *json_str = "{\"name\":\"John\",\"age\":30,\"city\":\"New York\"}";cJSON *json = cJSON_Parse(json_str);if (json == NULL) {printf("Error parsing JSON\n");return 1;}cJSON *name = cJSON_GetObjectItem(json, "name");cJSON *age = cJSON_GetObjectItem(json, "age");cJSON *city = cJSON_GetObjectItem(json, "city");printf("Name: %s\n", name->valuestring);printf("Age: %d\n", age->valueint);printf("City: %s\n", city->valuestring);cJSON_Delete(json);return 0;
運行結果:
Name: John
Age: 30
City: New York
`
4. 添加cJSON對象到鏈表
函數原型:cJSON *cJSON_CreateObject(void);
功能描述:創建一個空的cJSON對象。使用場景:當您需要創建一個新的JSON對象時,可以使用此函數。參數說明:無。返回值:返回指向cJSON結構體的指針。示例代碼:
cJSON *object = cJSON_CreateObject();cJSON_AddStringToObject(object, "name", "John");cJSON_AddNumberToObject(object, "age", 30);cJSON_AddStringToObject(object, "city", "New York");
//運行一下這個結果
char *json_str = cJSON_Print(object);printf("%s\n", json_str);
運行結果:
{"name":"John","age":30,"city":"New York"}
//添加到鏈表
cJSON *array = cJSON_CreateArray();cJSON_AddItemToArray(array, object);
//打印鏈表
char *array_str = cJSON_Print(array);printf("%s\n", array_str);
運行結果:
[{"name":"John","age":30,"city":"New York"}]
//刪除鏈表
cJSON_Delete(array);
//刪除對象
cJSON_Delete(object);
-
cJSON_GetArrayItem
函數原型:cJSON *cJSON_GetArrayItem(const cJSON *array, int item);功能描述:獲取數組中指定位置的元素。
使用場景:當您需要獲取數組中指定位置的元素時,可以使用此函數。
參數說明:array:指向cJSON數組的指針。item:要獲取的元素的位置。
返回值:返回指向cJSON結構體的指針。
示例代碼:
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h" int main() { // 創建一個JSON對象 cJSON *root = cJSON_CreateObject(); // 向JSON對象中添加數據 cJSON_AddStringToObject(root, "wxl", "boy"); cJSON_AddNumberToObject(root, "nianling", 20); cJSON_AddNumberToObject(root, "shengao", 178.0); // 假設身高是浮點數 // 創建一個數組 cJSON *array = cJSON_CreateArray(); cJSON_AddItemToArray(array, cJSON_CreateNumber(1)); cJSON_AddItemToArray(array, cJSON_CreateNumber(3)); cJSON_AddItemToArray(array, cJSON_CreateNumber(5)); cJSON_AddItemToArray(array, cJSON_CreateNumber(7)); cJSON_AddItemToArray(array, cJSON_CreateNumber(9)); // 將數組添加到JSON對象中 cJSON_AddItemToObject(root, "array", array); // 打印整個JSON對象 char *rendered = cJSON_Print(root); printf("%s\n", rendered); // 釋放分配的內存 cJSON_Delete(root); free(rendered); return 0;
}
運行結果:
{"wxl":"boy","nianling":20,"shengao":178,"array":[1,3,5,7,9]}
實戰案例
為了更好地理解CJSON庫的應用,我們將通過一個實戰案例來展示如何使用CJSON庫解析和生成JSON數據。
假設您正在開發一個物聯網設備,該設備需要接收來自云端的JSON格式的控制指令,并返回當前狀態給云端。我們可以使用CJSON庫來解析云端發送的JSON指令,并根據指令內容執行相應的操作
這里使用的是我之前一個項目,用到的云平臺是onenet
我收到的是這樣的json數據
```json
`{ "title": "屬性上報", "timestamp": "2024-07-05 09:46:21","message": "{\"topic\":\"$sys/squ938zsi0/device_hyw/thing/property/post\",\"data\":{\"id\":\"1720144597063\",\"version\":\"1.0\",\"params\":{\"gps\":{\"value\":{\"lon\":115,\"lat\":23}},\"heart_rate\":{\"value\":113},\"lat\":{\"value\":112},\"led_state\":{\"value\":1},\"lng\":{\"value\":23},\"n_sp02\":{\"value\":56},\"old_man_fell_down\":{\"value\":1},\"old_temp\":{\"value\":37}}}}" } ```
當解析到led_state等于1時候,進入自動模式,PC13的led燈打開,led_state等于0時候,進入手動模式,同時打印輸出當前的心率、血氧、溫度、經緯度、老人跌倒狀態
void OneNet_RevPro(unsigned char *cmd)
{ char *req_payload = NULL; char *cmdid_topic = NULL; unsigned short topic_len = 0; unsigned short req_len = 0; unsigned char qos = 0; static unsigned short pkt_id = 0; unsigned char type = 0; short result = 0; cJSON *root = NULL; cJSON *params = NULL; cJSON *led_state_obj = NULL; type = MQTT_UnPacketRecv(cmd); switch(type) { case MQTT_PKT_PUBLISH: result = MQTT_UnPacketPublish(cmd, &cmdid_topic, &topic_len, &req_payload, &req_len, &qos, &pkt_id); if(result == 0) { root = cJSON_Parse(req_payload); if (root != NULL) { // 假設 message 是一個包含完整 JSON 數據的字符串 cJSON *message_obj = cJSON_GetObjectItemCaseSensitive(root, "message"); if (cJSON_IsString(message_obj) && (message_obj->valuestring != NULL)) { cJSON *inner_root = cJSON_Parse(message_obj->valuestring); if (inner_root != NULL) { params = cJSON_GetObjectItemCaseSensitive(inner_root, "data"); if (params != NULL) { led_state_obj = cJSON_GetObjectItemCaseSensitive(params, "led_state"); if (led_state_obj != NULL && cJSON_IsNumber(led_state_obj)) { int led_state = led_state_obj->valueint; if (led_state == 1) { // 進入自動模式,打開 LED LED_Control(GPIOC, GPIO_Pin_13, Enable); } else if (led_state == 0) { // 進入手動模式,關閉 LED(如果需要) LED_Control(GPIOC, GPIO_Pin_13, Disable); // 打印輸出 printf("LED is off, manual mode\n"); } } // ... 其他參數處理 ...//當前的心率heart_rate_obj = cJSON_GetObjectItemCaseSensitive(params, "heart_rate"); if (heart_rate_obj != NULL && cJSON_IsNumber(heart_rate_obj)) { int heart_rate = heart_rate_obj->valueint; // 打印輸出 printf("Heart rate: %d\n", heart_rate); }} cJSON_Delete(inner_root); } } cJSON_Delete(root); } } MQTT_FreeBuffer(req_payload); break; // ... 其他 case ... } MQTT_FreeBuffer(cmdid_topic); ESP8266_Clear();
}
參考文章
- C語言中cJSON的使用
- C語言利用cJSON解析JSON格式全過程
總結
我們詳細講解了CJSON庫的核心函數,包括如何創建JSON對象、添加鍵值對、解析JSON字符串以及遍歷JSON對象等,為讀者打下了堅實的理論基礎。隨后,通過實際操作解析OneNET平臺返回的JSON數據,希望本教程能夠對大家在物聯網開發過程中有所幫助。最后呢,在編寫博客的過程中,我盡量保持內容的準確性和完整性,但也難免會有疏漏或錯誤之處。歡迎各位讀者指出其中的問題,幫助我不斷進步。謝謝大家的閱讀,