物联网数据解析实战:掌握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.mfbz.cn/a/777087.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

猫狗图像分类-划分数据集

&#x1f4da;博客主页&#xff1a;knighthood2001 ✨公众号&#xff1a;认知up吧 &#xff08;目前正在带领大家一起提升认知&#xff0c;感兴趣可以来围观一下&#xff09; &#x1f383;知识星球&#xff1a;【认知up吧|成长|副业】介绍 ❤️如遇文章付费&#xff0c;可先看…

【Linux】:程序地址空间

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关Linux程序地址空间的相关知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从…

css使用伪元素after或者before的时候想要给after设置z-index无效

css使用伪元素after或者before的时候想要给after或者before设置一个层级关系&#xff0c;使该伪类写入的样式在box的下面&#xff0c;发现给box设置z-index无效&#xff0c; 需要找到父级元素&#xff0c;在父级元素上设置z-index值并且将伪类设置z-index:-1

【Whisper】WhisperX: Time-Accurate Speech Transcription of Long-Form Audio

Abstract Whisper 的跨语言语音识别取得了很好的结果&#xff0c;但是对应的时间戳往往不准确&#xff0c;而且单词级别的时间戳也不能做到开箱即用(out-of-the-box). 此外&#xff0c;他们在处理长音频时通过缓冲转录

Spark快速大数据分析PDF下载读书分享推荐

《Spark 快速大数据分析》是一本为 Spark 初学者准备的书&#xff0c;它没有过多深入实现细节&#xff0c;而是更多关注上层用户的具体用法。不过&#xff0c;本书绝不仅仅限于 Spark 的用法&#xff0c;它对 Spark 的核心概念和基本原理也有较为全面的介绍&#xff0c;让读者能…

Elasticsearch:Runtime fields - 运行时字段(一)

目录 使用运行时字段带来的好处 激励 折衷 映射运行时字段 定义运行时字段而不使用脚本 忽略运行时字段上的脚本错误 更新和删除运行时字段 在搜索请求中定义运行时字段 创建使用其他运行时字段的运行时字段 运行时字段&#xff08;runtime fields&#xff09;是在查询…

golang结合neo4j实现权限功能设计

neo4j 是非关系型数据库之图形数据库&#xff0c;这里不再赘述。 传统关系数据库基于rbac实现权限, user ---- role ------permission,加上中间表共5张表。 如果再添上部门的概念&#xff1a;用户属于部门&#xff0c;部门拥有 角色&#xff0c;则又多了一层&#xff1a; user-…

WPF UI 界面布局 魔术棒 文字笔记识别 技能提升 布局功能扩展与自定义 继承Panel的对象,测量与排列 系列七

应用开发第一步 功能分类&#xff1a;页面上的功能区域划分。。。。需求分析 业务逻辑 数据流 功能模块 UI/UX 编码 测试 发布 功能开发与布局 不用显式的方式设定元素的尺寸 不使用屏幕坐标来指定位置 Grid 功能最强大&#xff0c;布局最灵活的容器…

代码提交错分支了怎么办?

你有么有遇到过正在开发的代码&#xff0c;提交到生产环境的分支去&#xff0c;遇到这种情况怎么办&#xff1f; 问题重现&#xff1a; 这段注释// AAAAAAAAAAA 本来应该写在dev分支的&#xff0c;现在提交并push到master分支了 现在第一步&#xff0c;撤回提交 第二步&…

第五届机械工程与智能制造国际学术会议(MEIM 2024,7月26-28)

第五届机械工程与智能制造国际学术会议(MEIM 2024) 计划2024年7月26-28日在中国辽宁锦州隆重举行。本次会议由辽宁理工学院主办。 会议主要围绕机械工程与智能制造等研究领域展开讨论&#xff0c;旨在为从事机械工程与智能制造研究的专家学者、程技术人员、技术研发人员提供一个…

Midjourney 如何使用参考图像来提升图像的准确性和相似度?

🧙🏼图像提示 🧙🏼‍♂️ 您可以使用图像作为提示的一部分来影响作业的构图、样式和颜色。图像提示可以单独使用,也可以与文本提示一起使用 - 尝试组合具有不同样式的图像以获得最令人兴奋的结果。 🛠️实际图像提示操作步骤 点击加号按钮,双击上传文件,把小黄猫…

SwiftUI 6.0(iOS 18.0)滚动视图新增的滚动阶段(Scroll Phase)监听功能趣谈

何曾几时&#xff0c;在 SwiftUI 开发中的秃头小码农们迫切需要一种能够读取当前滚动状态的方法。 在过去&#xff0c;他们往往需要借助于 UIKit 的神秘力量。不过这一切在 SwiftUI 6.0 中已成“沧海桑田”。 在本篇博文中&#xff0c;您将学到如下内容&#xff1a; 1. Scroll…

Anubi WebKey开启去中心化数字革命的新纪元

随着技术的飞速发展&#xff0c;Web3正在重新定义未来互联网的架构&#xff0c;标志着从集中式控制向去中心化自主的历史性转变。在这场全球性的技术演变中&#xff0c;Anubi WebKey不仅仅是一款前沿的智能设备&#xff0c;它代表的是一种划时代的技术革命&#xff0c;一个重塑…

24.【C语言】getchar putchar的使用

1.基本作用 用户输入字符&#xff0c;getchar()获取字符&#xff08;含\n:即键入的Enter&#xff09;&#xff08;字符本质上是以ASCII值或EOF&#xff08;-1&#xff09;存储的&#xff09;&#xff08;与scanf有区别&#xff09; putchar() 打印字符&#xff08;把得到的A…

图像畸变矫正与透视变换

图像畸变矫正与透视变换 Halcon自动生成的圆形棋盘格Halcon透视变换 Halcon自动生成的圆形棋盘格 示例程序&#xff1a; *生成棋圆形棋盘格 行 列 直径 直径/距离比值 gen_caltab (12, 9, 0.002, 0.5, caltab_12X9.descr, caltab.ps) *生成相机参数 焦距 畸变系数 X解析度 Y解…

计算云服务1

前言 一直以来&#xff0c;计算资源都是整个企业业务系统发展所需的大动脉&#xff0c;没有计算资源&#xff0c;企业业务就无法正常运行。在云计算的时代里&#xff0c;计算服务也是云服务中的第一大类服务&#xff0c;计算资源的重要性由此可见。本章&#xff0c;我们将带领…

【数据结构】常见四类排序算法

1. 插入排序 1.1基本思想&#xff1a; 直接插入排序是一种简单的插入排序法&#xff0c;其基本思想是&#xff1a;把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中&#xff0c;直到所有的记录插入完为止&#xff0c;得到一个新的有序序列 。实际中我们…

HTML5+JavaScript单词游戏

HTML5 JavaScript单词游戏 数据字典格式&#xff1a;每行一个 单词 &#xff0c;单词和解释用空格分隔&#xff0c;如 a art.一(个)&#xff1b;每一(个) ability n.能力&#xff1b;能耐&#xff0c;本领 able a.有能力的&#xff1b;出色的 baby n.婴儿&#xff1b;孩子…

NET程序开发可能会用到的一些资料文档

NET程序开发使用的一些资料文件&#xff0c;NET高级调试&#xff0c;NET关键技术深入解析&#xff0c;WPF专业编程指南&#xff0c;程序员求职攻略&#xff0c;WPF编程宝典等。 下载链接&#xff1a;https://download.csdn.net/download/qq_43307934/89518582

Python入门 2024/7/6

目录 数据容器入门 列表的定义语法 基本语法 嵌套列表 ​编辑 列表的下表索引 ​编辑 列表的常用操作 列表的常见方法 查找元素的下标 修改下标索引的值 插入元素 追加元素 追加一批元素 删除元素 删除某元素在列表中的第一个匹配项 清空列表内容 统计元素在…