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

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

原本以为在写上一条引用的时候可以把这篇完成,结果中途又遇到了一些问题,自己对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,与君共勉于技术之路上

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容