物聯網數據解析實戰:掌握CJSON庫核心函數,精準處理JSON數據

物聯網數據解析實戰:掌握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庫的解析函數

  1. 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"
    }
  2. 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);
  1. 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();  
}  

參考文章

  1. C語言中cJSON的使用
  2. C語言利用cJSON解析JSON格式全過程

總結

我們詳細講解了CJSON庫的核心函數,包括如何創建JSON對象、添加鍵值對、解析JSON字符串以及遍歷JSON對象等,為讀者打下了堅實的理論基礎。隨后,通過實際操作解析OneNET平臺返回的JSON數據,希望本教程能夠對大家在物聯網開發過程中有所幫助。最后呢,在編寫博客的過程中,我盡量保持內容的準確性和完整性,但也難免會有疏漏或錯誤之處。歡迎各位讀者指出其中的問題,幫助我不斷進步。謝謝大家的閱讀,

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/40314.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/40314.shtml
英文地址,請注明出處:http://en.pswp.cn/web/40314.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

部署Gunicorn + Flask應用到Docker

部署Gunicorn Flask應用到Docker中涉及幾個步驟&#xff0c;下面是一個基本的指南&#xff1a; 1. 創建Flask應用 首先&#xff0c;確保你有一個可用的Flask應用。這里有一個簡單的示例&#xff1a; from flask import Flask app Flask(__name__)app.route(/) def hello_w…

pandas,dataframe使用筆記

目錄 新建一個dataframe不帶列名帶列名 dataframe添加一行內容查看dataframe某列的數據類型新建dataframe時設置了列名&#xff0c;則數據類型為object dataframe的保存保存為csv文件保存為excel文件 dataframe屬于pandas 新建一個dataframe 不帶列名 df pd.DataFrame() 帶…

GuLi商城-商品服務-API-品牌管理-效果優化與快速顯示開關

<template><div class"mod-config"><el-form :inline"true" :model"dataForm" keyup.enter.native"getDataList()"><el-form-item><el-input v-model"dataForm.key" placeholder"參數名&qu…

華為交換機 LACP協議

華為交換機支持的LACP協議&#xff0c;即鏈路聚合控制協議&#xff0c;是一種基于IEEE 802.3ad標準的動態鏈路聚合與解聚合的協議。它允許設備根據自身配置自動形成聚合鏈路并啟動聚合鏈路收發數據。 在LACP模式下&#xff0c;鏈路聚合組能夠自動調整鏈路聚合&#xff0c;維護…

java集合(1)

目錄 一.集合概述 二. 集合體系概述 1. Collection接口 1.1 List接口 1.2 Set接口 2. Map接口 三. ArrayList 1.ArrayList常用方法 2.ArrayList遍歷 2.1 for循環 2.2 增強for循環 2.3 迭代器遍歷 一.集合概述 我們經常需要存儲一些數據類型相同的元素,之前我們學過…

Java 基礎語法

Java 是一種面向對象的編程語言&#xff0c;具有簡單、健壯、安全、跨平臺等特點。下面是Java基礎語法的詳細介紹&#xff0c;并附帶一些示例說明&#xff1a; ### 1. 變量和數據類型 Java 中的變量用于存儲數據&#xff0c;必須先聲明后使用。Java 的數據類型分為基本數據類…

C++ 仿QT信號槽二

// 實現原理 // 每個signal映射到bitset位&#xff0c;全集 // 每個slot做為signal的bitset子集 // signal全集觸發&#xff0c;標志位有效 // flip將觸發事件隊列前置 // slot檢測智能指針全集觸發的標志位&#xff0c;主動運行子集綁定的函數 // 下一幀對bitset全集進行觸發清…

【C++】 解決 C++ 語言報錯:Segmentation Fault

文章目錄 引言 段錯誤&#xff08;Segmentation Fault&#xff09;是 C 編程中常見且令人頭疼的錯誤之一。段錯誤通常發生在程序試圖訪問未被允許的內存區域時&#xff0c;導致程序崩潰。本文將深入探討段錯誤的產生原因、檢測方法及其預防和解決方案&#xff0c;幫助開發者在…

Lex Fridman Podcast with Andrej Karpathy

我不太喜歡Lex Fridman的聲音&#xff0c;總覺得那讓人昏昏欲睡&#xff0c; 但無奈他采訪的人都太大牌了&#xff0c;只能去聽。但是聽著聽著&#xff0c;就會覺得有深度的采訪這些人&#xff0c;似乎也只有他這種由研究員背景的人能干&#xff0c; 另&#xff0c;他提的問題確…

4.2 投影

一、投影和投影矩陣 我們以下面兩個問題開始&#xff0c;問題一是為了展示投影是很容易視覺化的&#xff0c;問題二是關于 “投影矩陣”&#xff08;projection matrices&#xff09;—— 對稱矩陣且 P 2 P P^2P P2P。 b \boldsymbol b b 的投影是 P b P\boldsymbol b Pb。…

android的dump_processe中anon和swap字段的含義是什么?計算進程占用內存大小是否可以用這兩個字段相加?

在Android系統中&#xff0c;dump_processes 命令或類似機制&#xff08;如通過 adb shell dumpsys&#xff09;的輸出中&#xff0c;可能會包含與進程內存使用相關的信息&#xff0c;但通常不直接以 anon 和 swap 作為字段名。不過&#xff0c;基于您的提問&#xff0c;我可以…

嵌入式學習——硬件(Linux內核驅動編程LED、蜂鳴器、按鍵)——day59

1. 編寫LED驅動&#xff08;初始化所有子設備號&#xff09; #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <asm/uaccess.h> #include <asm/io.h>#define GPBCON (0x5…

2024年7月5日 (周五) 葉子游戲新聞

老板鍵工具來喚去: 它可以為常用程序自定義快捷鍵&#xff0c;實現一鍵喚起、一鍵隱藏的 Windows 工具&#xff0c;并且支持窗口動態綁定快捷鍵&#xff08;無需設置自動實現&#xff09;。 卸載工具 HiBitUninstaller: Windows上的軟件卸載工具 《樂高地平線大冒險》為何不登陸…

江漢大學劉春萌同學整理的wifi模塊 上傳mqtt實驗步驟

一.固件燒錄 1.打開安信可官網 2.點擊wifi模組系列的ESP8266 3.點擊各類固件后選擇固件號1471下載 4.打開燒錄工具將下載的二進制文件導入并將后面的起始地址寫為0x00000,下面勾選40mhz QIO 8Mbit點擊start下載即可 二.本地部署mqtt服務器(windows) 1.下載mosquitto后有一個m…

Java并發編程知識整理筆記

目錄 ?1. 什么是線程和進程&#xff1f; 線程與進程有什么區別&#xff1f; 那什么是上下文切換&#xff1f; 進程間怎么通信&#xff1f; 什么是用戶線程和守護線程&#xff1f; 2. 并行和并發的區別&#xff1f; 3. 創建線程的幾種方式&#xff1f; Runnable接口和C…

微博視頻下載

video_urls 獲取xpath://video/src|//video/autoplay # !/usr/bin/python3 # -*- coding:utf-8 -*- """ author: JHC000abcgmail.com file: demo1.py time: 2024/6/3 18:00 desc:""" import os import re import requests from urllib.parse im…

Qt實現流動的管道效果代碼示例

在現代圖形用戶界面&#xff08;GUI&#xff09;應用程序中&#xff0c;動態效果可以顯著增強用戶體驗。本文將介紹如何使用Qt框架實現一個流動的管道效果。我們將通過自定義QWidget來繪制管道&#xff0c;并使用定時器來實現流動效果。 1. 準備工作 首先&#xff0c;確保你已…

LeetCode.68文本左右對齊

問題描述 給定一個單詞數組 words 和一個長度 maxWidth &#xff0c;重新排版單詞&#xff0c;使其成為每行恰好有 maxWidth 個字符&#xff0c;且左右兩端對齊的文本。 你應該使用 “貪心算法” 來放置給定的單詞&#xff1b;也就是說&#xff0c;盡可能多地往每行中放置單詞…

HMI 的 UI 風格創造奇跡

HMI 的 UI 風格創造奇跡

Table-driven Declarative Rewrite Rule (DRR)

Table-driven Declarative Rewrite Rule (DRR 好處規則定義原模式基于位置的匹配操作的匹配有向無環圖&#xff08;DAG&#xff09;(AOp (BOp), $attr): 綁定操作的結果 好處 模式創建者只需要聲明性地指定重寫模式&#xff0c;而不必擔心調用具體的C方法。 消除樣板代碼&…