美文网首页
智能硬件数据传输之CJSON转化

智能硬件数据传输之CJSON转化

作者: creker | 来源:发表于2017-09-22 15:12 被阅读0次

    来点儿干货,今天白天主要时间都在车上,于是继续完善这篇文章。

    原本以为在写上一条引用的时候可以把这篇完成,结果中途又遇到了一些问题,自己对JSON的语法规则并没有很理解,这是停留在应用层面。于是,在业余时间,挤了挤时间,看了一些JSON的语法知识。

    前言

    • 写技术文章确实是一件很难的事情,写出来容易,要自己理解,同时还要让读者看懂,真的是一件很不容易的事情。与君共勉。

    1 概述

    • 物联网产品免不了和服务器做交互,目前使用的比较多的是以太网接网线或者WiFi设备或者GPRS。
    • 无论是用的透传,还是非透传的方式,都需要将硬件产生的原始数据转换为服务器端的物联网数据,硬件处理服务端的物联网数据时,也需要转化为十六进制的数据,方便处理。
    • 这里涉及到了两个问题,JSON数据包的解析和组装。
    • 硬件设备使用的基本都是C语言,同时考虑成本等因素,单片机的RAM也是KB级的比较多。
    • 此文章重点讲解一下一个非常好用的CJSON库,在MDK中编译的代码量只有十几KB,占用的RAM只有几KB
    • 该JSON库具有占用空间小(ROM占用10K以内,易移植(只有一个c文件和一个h文件),使用简单(只需要掌握几个常用的函数,和一个CJSON结构体就可以轻松地使用)的特点。包含到项目源码中非常方便,而且其实现效率也是非常高的。

    2 JSON

    • 先贴一段JSON数据,阅读下文时可以参考一下对应的数据格式
    {
        "msg": [
            {
                "ctime": "20170916091927",
                "gateLine": "ON",
                "locksId": 65,
                "isLocked": true,
                "locksNo": "1001001105",
                "pwd": {
                    "1": "654321",
                    "2": "147258"
                }
            },
            {
                "ctime": "20170916091927",
                "gateLine": "ON",
                "locksId": 66,
                "isLocked": false,
                "locksNo": "1001001106",
                "pwd": {
                    "1": "123456",
                    "2": “147258"
                }
            }
        ],
        "code": 0
    }
    
    • 下文对JSON的介绍来自笔者看了大量教程以后的总结。

    2.1JSON 语法规则

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。

    1. 结构特点
    • 数据在名称/值对中
    • 数据由逗号分隔
    • 大括号保存对象
    • 中括号保存数组
    • 键、值可层层嵌套
    1. 说明一下:键、值可层层嵌套
    • 理解该特点是运用JSON的关键。
    • JSON的值可以为以下类型:
      数字(整数或浮点数)
      字符串(在双引号中)
      逻辑值(true 或 false)
      数组(在方括号中)
      对象(在花括号中)
      null(在不同的语言表示的意义不一样,开发者只需要知道在自己的语言里的意义就可以了)
    • JSON的值为数组时,数组可以是数字数组,字符串数组,对象数组等,所以该值里面又会包含很多键值对
    • 解析JSON的核心也是一层一层地往外拨,反复地调用一个或者两个方法(下文会详细介绍)

    2.2 JSON值

    2.2.3 JSON数字

    "locksId": 65,

    2.2.4 JSON字符串

    "ctime": "20170916091927",

    2.2.5 JSON逻辑值

    "isLocked": false,

    2.2.6 JSON数组

    • "msg"对应的值为一个数组,数组里面有两个对象(花括号)元素,
        "msg": [
            {
                "ctime": "20170916091927",
                "gateLine": "ON",
                "locksId": 65,
                "isLocked": true,
                "locksNo": "1001001105",
                "pwd": {
                    "1": "654321",
                    "2": "147258"
                }
            },
            {
                "ctime": "20170916091927",
                "gateLine": "ON",
                "locksId": 66,
                "isLocked": false,
                "locksNo": "1001001106",
                "pwd": {
                    "1": "123456",
                    "2": “147258"
                }
            }
        ],
    

    2.2.7 JSON对象

    • 一个对象里面一般会包含多种类型的值,里面的“pwd”对应的值也是一个对象
            {
                "ctime": "20170916091927",
                "gateLine": "ON",
                "locksId": 66,
                "isLocked": false,
                "locksNo": "1001001106",
                "pwd": {
                    "1": "123456",
                    "2": “147258"
                }
            }
    

    看到,应该可以深入感受一下上文提到的"键、值可层层嵌套"

    2.2.8 介绍一下JSON数据格式

    • Object,Item,Array

    笔者需要补充一下json的数据格式,学习中。。。。。。

    • 该小节作为一章的内容放在了第2章中。

    3 介绍CJOSN的结构

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

    这个结构体包含了所有的返回数据类型。

    4 介绍CJSON的解析

    4.1 解析使用的核心函数如下

     cJSON *cJSON_Parse(const char *value);
     void   cJSON_Delete(cJSON *c);
     int      cJSON_GetArraySize(cJSON *array);
     cJSON *cJSON_GetArrayItem(cJSON *array,int item);
     cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
    
    1. 一共五个函数, 前三个函数使用的位置和方法都很固定,后两个就是在获取数据的时候反复调用,目的就是走到JSON数据的最底部--获取健值。
    2. 总结一下就是:三个函数固定使用,目的是获取待处理的数据或者做收尾工作;两个函数反复使用,目的是一层一层往下,获取到基本数据。
     cJSON *cJSON_Parse(const char *value);
    
    • 该函数是接收到json字符串时,将字符串转为json格式的字符串,一般都是在解析的第一行主要代码的位置。
     void   cJSON_Delete(cJSON *c);
    
    • 该函数是在解析完成以后,用于释放内存。
     int      cJSON_GetArraySize(cJSON *array);
    
    • 该函数是在有数组的时候,且不知道数组长度的情况下,获取数组的长度,然后再用循环挨个解析数组。如果需要解析的数据里面没有数组的话,或者可以知道数组的具体长度的话,就不需要使用该函数。
    1. 下面是两个最重要的函数,熟练掌握了这两个函数,大多数的场景都可以应对了。
     cJSON *cJSON_GetArrayItem(cJSON *array,int item);
    
    • 该函数的作用是获取数组里面的元素,元素可以是对象,字符串,数值等各种类型。
    cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
    
    • 该函数的作用是获取对象里面,键对应的值。

    4.2 解析举例说明

    4.2.1数据分析

    • 还是用上面的的例子,贴下源数据
    {
        "msg": [
            {
                "ctime": "20170916091927",
                "gateLine": "ON",
                "locksId": 65,
                "isLocked": true,
                "locksNo": "1001001105",
                "pwd": {
                    "1": "654321",
                    "2": "147258"
                }
            },
            {
                "ctime": "20170916091927",
                "gateLine": "ON",
                "locksId": 66,
                "isLocked": false,
                "locksNo": "1001001106",
                "pwd": {
                    "1": "123456",
                    "2": “147258"
                }
            }
        ],
        "code": 0
    }
    
    • 简单分析一下
      分析务必搞清楚几点:
      1.第二章里面介绍的结构
      2.上文提到的五个方法,有不明白的可往上翻
    1. 最外围结构为一个对象(花括号)。使用cJSON_Parse就可以获取到JSON对象内容
    2. 对象当中包含了两个Item,分别是"msg"和"code"。
    3. "code"对应的是一个数字,一次解析可以获得数据。使用cJSON_GetObjectItem,获取返回的int类型数据
    4. "msg"里面包含了一个JSON数组,每个数组的元素为一个对象。使用cJSON_GetObjectItem,返回值是一个array
    5. 先获取到array的数量。使用cJSON_GetArraySize
    6. 用for循环对每个数组里面的对象元素做解析cJSON_GetArrayItem,返回一个对象
    7. 反复对对象做解析,就可以获取所有的数据。反复使用cJSON_GetObjectItem

    4.2.2 贴一小段代码示例

    • 笔者不喜欢贴代码,虽然很多读者都喜欢直接看代码
    • 还是那句话,看代码引用起来快,但是后期维护更多的时间来搞清楚算法
    • 下面提到的步骤1,2,3,4....对应上文简单分析的7个步骤,一一对应看即可。
    步骤1
        Mother_obj=cJSON_Parse(json_string);
                                                    //json_string为源数据的字符数组
                                                    //Mother_obj为整个花括号对应的对象
    
    步骤2,3
        arry_obj_item = cJSON_GetObjectItem(Mother_obj,"code");
        json_int_buf=arry_obj_item->valueint;
                                                    //获取code的值
    
    步骤4
        array = cJSON_GetObjectItem(Mother_obj,"msg");
                                                    //获取“msg”的数组值
    
    步骤5
    lock_array_len = cJSON_GetArraySize(array);
                                                    //获取数组里面的元素个数
    
    步骤6,7
            for(i=0;i<lock_array_len;i++){
    
                array_obj = cJSON_GetArrayItem(array,i);
                                                    //获取数组里面的元素对象
    //后面就对对象做处理,反复调用cJSON_GetObjectItem即可
                if(array_obj==NULL)continue;
    //获取“time”对应的值
                arry_obj_item = cJSON_GetObjectItem(array_obj,"ctime");
                if(arry_obj_item==NULL)continue;
                json_buf = arry_obj_item->valuestring;
    //获取“lockId”对应的值
                arry_obj_item = cJSON_GetObjectItem(array_obj,"locksId");
                if(arry_obj_item==NULL)continue;
                json_int_buf = arry_obj_item->valueint;
            }   
    

    按照层层嵌套的逻辑,就可以解析出整个字符串

    5 介绍CJSON的数据组合

    • 下一篇继续介绍

    CrekerLi,与君共勉于技术之路上

    相关文章

      网友评论

          本文标题:智能硬件数据传输之CJSON转化

          本文链接:https://www.haomeiwen.com/subject/pylssxtx.html