• 【嵌入式项目应用】__cJSON在单片机的使用


    目录

    前言

    一、JSON和cJson

    二、cJSON是如何表示JSON数据的

    三、如何封装完整的JSON数据

    1. 先将串口打通,方便电脑查看log日志。

    2. 增加cjson.c文件,已经在main.c中

    3. 准备打包如下的JSON包

    4. 代码部分,先将几个部分初始化指针

    5. 创建链表

    6. 我们查看添加的是否正确,可以将链表通过串口打印出来。

     7. 效果如下:

    四、解包

    五、总结

    (* ̄︶ ̄)创作不易!期待你们的 点赞、收藏和评论喔。 


    前言

    在使用MQTT传输数据的时候,经常使用到JSON包,来进行数据的交互,这篇文章讲一下该如何使用。

    一、JSON和cJson

    • JSON:全称 JavaScript Object Notation,轻量级的数据格式。
    • cJSON:是一个用c语言编写的JSON数据解析器,超级轻便,可以移植,单文件MIT源协议。

    cJSON的源码文件只有两个:

    cJSON.c

    cJSON.h

    下载地址可以在github下载,地址如下:

    GitHub - DaveGamble/cJSON: Ultralightweight JSON parser in ANSI C

    将这两个文件下载之后,添加到项目中,其它.C文件调用的时候,需要包含头文件cJSON.h即可,文件在MDK中的位置如下:

    二、cJSON是如何表示JSON数据

     cJSON是用一个结构体来表示一个JSON数据,定义在cJSON.h中,查看如下源码:

    1. /* The cJSON structure: */
    2. typedef struct cJSON
    3. {
    4. /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
    5. struct cJSON *next;
    6. struct cJSON *prev;
    7. /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
    8. struct cJSON *child;
    9. /* The type of the item, as above. */
    10. int type;
    11. /* The item's string, if type==cJSON_String and type == cJSON_Raw */
    12. char *valuestring;
    13. /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
    14. int valueint;
    15. /* The item's number, if type==cJSON_Number */
    16. double valuedouble;
    17. /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
    18. char *string;
    19. } cJSON;

    不是存贮整片的JSON数据,而是按照每条数据进行存储的。使用next指针和prev指针进行链表,存储整片的JSON数据。

    三、如何封装完整的JSON数据

    说了这么多,我们实际操作一下,找一块STM32F开发板,测试一下。

    1. 先将串口打通,方便电脑查看log日志。

    1. uart_init(115200);

    2. 增加cjson.c文件,已经在main.c中

    1. #include "cJSON.h"

     

    3. 准备打包如下的JSON包

    1. {
    2. "我的名字": "老刘",
    3. "公众号": "数独机",
    4. "年龄": 11,
    5. "性别": "男",
    6. "电话": 186,
    7. "地址": "一般人不告诉",
    8. "我是嵌套的cJSON": {
    9. "号码": 9527,
    10. "传真": 5510,
    11. "淘宝店": "This熏"
    12. },
    13. "我是嵌套的数组": [{
    14. "我是奇数循环": 0
    15. }, {
    16. "我是偶数循环": "12365"
    17. }, {
    18. "我是奇数循环": 2
    19. }, {
    20. "我是偶数循环": "12365"
    21. }, {
    22. "我是奇数循环": 4
    23. }]
    24. }

    4. 代码部分,先将几个部分初始化指针

    1. cJSON* main_root = NULL;
    2. cJSON* main_m_root = NULL;
    3. cJSON* main_l_root = NULL;
    4. cJSON* obj=NULL;
    5. char* response_str = NULL;

    5. 创建链表

    main_root = cJSON_CreateObject();

     豪横的在链表中添加节点

    1. cJSON_AddStringToObject(main_root, "我的名字", "老刘");
    2. cJSON_AddStringToObject(main_root, "公众号", "数独机");
    3. cJSON_AddNumberToObject(main_root, "年龄", 11);
    4. cJSON_AddStringToObject(main_root, "性别", "男");
    5. cJSON_AddNumberToObject(main_root, "电话", 186);
    6. cJSON_AddStringToObject(main_root, "地址", "一般人不告诉");
    7. main_m_root = cJSON_CreateObject();
    8. cJSON_AddNumberToObject(main_m_root, "号码", 9527);
    9. cJSON_AddNumberToObject(main_m_root, "传真", 5510);
    10. cJSON_AddStringToObject(main_m_root, "淘宝店", "This熏");
    11. cJSON_AddItemToObject(main_root, "我是嵌套的cJSON", main_m_root);
    12. main_l_root=cJSON_CreateArray();
    13. cJSON_AddItemToObject(main_root,"我是嵌套的数组",main_l_root);
    14. for(i=0;i<5;i++)
    15. {
    16. obj=cJSON_CreateObject();
    17. cJSON_AddItemToArray(main_l_root,obj);
    18. if(i%2 == 0) cJSON_AddNumberToObject(obj, "我是奇数循环", i);
    19. else cJSON_AddStringToObject(obj, "我是偶数循环", "12365");
    20. }

    6. 我们查看添加的是否正确,可以将链表通过串口打印出来。

    1. response_str = cJSON_Print(main_root);
    2. printf("%s\n",response_str);

     7. 效果如下:

    四、解包

    解包的函数只有一个:

    1. CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);

    还是用例子进行讲解:

    将串口的数据完全接收到一个大的缓冲区里面,当然这个数据也可以来自wifi或者网络。

    1. if(GET_STOP_flag)
    2. {
    3. for(i=0;i<(cJSON_pack_StopP-cJSON_pack_FistP)+1;i++)
    4. {
    5. MessageTmp[i] =WIFI_RC_buf[cJSON_pack_FistP-1+i];
    6. }
    7. }
    1. GET_STOP_flag //为停止接收标志;
    2. cJSON_pack_StopP //停止指针位置
    3. cJSON_pack_FistP //开始指针位置
    4. MessageTmp //临时的数组

    只需要对临时的数组进行操作即可。开辟内存空间,将数组转换为字符串。

    1. MessageStrTmp = (char *)cJSON_malloc(sizeof(char) * (sizeof(MessageTmp) + 1));
    2. strncpy(MessageStrTmp, MessageTmp, sizeof(MessageTmp));

    使用解包函数

    1. //接收解包过程
    2. Thisxun_root = cJSON_Parse(MessageStrTmp);
    3. Thisxun_root_type = cJSON_GetObjectItem(hiss_root,"type")->valuestring;
    4. if(strcmp(Thisxun_root_type,TYPE_USER_INFO_SYNC)==0)
    5. {
    6. Thisxun_insDetail = cJSON_GetObjectItem(Thisxun_root,"insDetail");
    7. userID = cJSON_GetObjectItem(Thisxun_insDetail,"userId")->valuestring;
    8. password = cJSON_GetObjectItem(Thisxun_insDetail,"password")->valuestring;
    9. }

    五、总结

    每次封包和解包结束之后,都要及时释放内存

    1. cJSON_Delete(Thisxun_root);
    2. cJSON_free(MessageStrTmp);

    对于单片机而言,需要修改Heap_Size


    (* ̄︶ ̄)创作不易!期待你们的 点赞收藏评论喔。 

    本文来源网络,免费分享知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除!

  • 相关阅读:
    Python格式化字符串(格式化输出)
    【VsCode】vscode创建文件夹有小图标显示和配置
    CSDN第11次竞赛题解与总结
    【Tensorflow深度学习】实现手写字体识别、预测实战(附源码和数据集 超详细)
    MASA Stack 第四期社区例会
    一文详细讲解 io_uring
    代码风格改善
    多态语法详解
    【linux学习】管道符,重定向与环境变量
    asp.net core服务限制堆内存大小
  • 原文地址:https://blog.csdn.net/weixin_44807874/article/details/134020455