查看: 294|回复: 0

cJSON扩展库说明

[复制链接]

28

主题

66

帖子

1167

积分

版主

Rank: 7Rank: 7Rank: 7

积分
1167
发表于 2023-12-12 15:47:50 | 显示全部楼层 |阅读模式
本帖最后由 LZY825597017 于 2023-12-12 15:47 编辑


cJSON扩展库说明
1-概述
JSON —— 轻量级的数据格式
JSON 全称 JavaScript Object Notation,即 JS对象简谱,是一种轻量级的数据格式。
它采用完全独立于编程语言的文本格式来存储和表示数据,语法简洁、层次结构清晰,易于人阅读和编写,同时也易于机器解析和生成,有效的提升了网络传输效率。

JSON语法规则
JSON对象是一个无序的"名称/"键值对的集合:
"{“开始,以”}"结束,允许嵌套使用;
每个名称和值成对出现,名称和值之间使用":"分隔;
键值对之间用","分隔
在这些字符前后允许存在无意义的空白符;
对于键值,可以有如下值:
一个新的json对象
数组:使用“[”“]”表示
数字:直接表示,可以是整数,也可以是浮点数
字符串:使用引号"表示
字面值:falsenulltrue中的一个(必须是小写)
示例如下:
//GET http://www.haohaodada.com/project/weather/ 请求返回的JSON数据格式
{
    "results": [
        {
            "location": {
                "id": "WTMKQ069CCJ7",
                "name": "\u676d\u5dde",
                "country": "CN",
                "nowtime": "2022-12-30 14:04:22"
            },
            "daily": [
                {
                    "date": "2022-12-30",
                    "text_day": "\u591a\u4e91",
                    "code_day": "4",
                    "text_night": "\u6674",
                    "code_night": "1",
                    "high": "8",
                    "low": "1",
                    "rainfall": "0.00",
                    "precip": "0.00",
                    "wind_direction": "\u65e0\u6301\u7eed\u98ce\u5411",
                    "wind_direction_degree": "",
                    "wind_speed": "8.4",
                    "wind_scale": "2",
                    "humidity": "86"
                }
            ],
            "last_update": "2022-12-30T08:00:00+08:00"
        }
}

cJSON是一个使用C语言编写的JSON数据解析器,具有超轻便,可移植,单文件的特点,使用MIT开源协议。cJSON内部运用列表和结构体来实现,封装JSON数据的过程,其实就是创建链表和向链表中        添加节点的过程,解析的过程其实就是剥离一个一个链表节点(键值对)的过程。
cJSON的设计思想从其数据结构上就能反映出来。
cJSON使用cJSON结构体来表示一个JSON数据,定义在cJSON.h中,源码如下:

/* The cJSON structure: */
typedef struct cJSON
{
    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
    struct cJSON *next;
    struct cJSON *prev;
    /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
    struct cJSON *child;

    /* The type of the item, as above. */
    int type;

    /* The item's string, if type==cJSON_String  and type == cJSON_Raw */
    char *valuestring;
    /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
    int valueint;
    /* The item's number, if type==cJSON_Number */
    double valuedouble;

    /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
    char *string;
} cJSON;


cJSON的设计很巧妙。
首先,它不是将一整段JSON数据抽象出来,而是将其中的一条JSON数据抽象出来,也就是一个键值对,用上面的结构体 strcut cJSON 来表示,其中用来存放值的成员列表如下:
String:用于表示该键值对的名称;
type:用于表示该键值对中值的类型;
valuestring:如果键值类型(type)是字符串,则将该指针指向键值;
valueint:如果键值类型(type)是整数,则将该指针指向键值;
valuedouble:如果键值类型(type)是浮点数,则将该指针指向键值;
其次,一段完整的JSON数据中由很多键值对组成,并且涉及到键值对的查找、删除、添加,所以使用链表来存储整段JSON数据,如上面的代码所示:
next指针:指向下一个键值对
prev指针指向上一个键值对
最后,因为JSON数据支持嵌套,所以一个键值对的值会是一个新的JSON数据对象(一条新的链表),也有可能是一个数组,方便起见,在cJSON中,数组也表示为一个数组对象,用链表存储,所以:
在键值对结构体中,当该键值对的值是一个嵌套的JSON数据或者一个数组时,由child指针指向该条新链表。
cJSON项目托管在Github上,仓库地址如下:

2-图形化快
1.cJSON初始化
image.png
如果需要对JSON数据解析,需要使用这条指令进行库的初始化,主要对内存进行分配。如果在FreeRTOS环境下,这一条语句将使用FreeRTOS的分配内存以及释放内存的方法,如果不使用,则默认使用C库自带的内存分配及释放方法。

2.把字符串转换成cJSON对象
这条指令可以将字符串数据转换成JSON结构体。

3.cJSON对象是否转换成功
image.png
这条指令可以判断对象是否转换成功。即判断解析出来的指针是否为空。被解析的字符串符合CJSON数据格式一般情况下,都不会失败。

4.cJSON解析到新对象
image.png
(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
根据键值对的名称从链表中取出对应的值,返回该键值对(链表节点)的地址。

5.cJSON获取子对象
image.png
cJSON *new_obj=obj->child;
配合解析对象模块一起使用来层层剥离嵌套数据出来。

6. cJSON获取对应KEY的数据
image.png
cJSON_GetObjectItem(obj,"key")->valuestring;
     根据KEY值类型,选择对应的字符串/整形/双浮点型/逻辑型。如果是数组类型,请使用如下语句来处理;
image.png
cJSON_GetArraySize(arr_obj)
cJSON_GetArrayItem(arr_obj,"key")->valuestring

7. cJSON对象清除
image.png
cJSON_Delete(obj);
      内存及时释放,cJSON的所有操作都是基于链表的,所以cJSON在使用过程中大量的使用malloc从堆中分配动态内存的,所以在使用完之后,应当及时清空cJSON指针所指向的内存,该函数也可用于删除某一条数据,该函数删除一条JSON数据时,如果有嵌套,会连带删除。
例1:
image.png
1. 通过GET请求获取String类型的字符串数据。
2. weather属于String类型,不是C语言通用的字符串类型,所以先通过weather.c_str()转换,再转换成CJSON结构体对象。
3. 先获取最外面的"results": []对象。
4. 获取"results": []下面的子对象:"location""daily""last_update"
5. 在获取第二层的" location ": []对象。
6. 根据键值"nowtime"字符串获取对应的数据"2022-12-30 14:04:22"字符串。
7. 通过串口打印字符串数据

例2:
image.png
String str2 = {"results":[{"location":{"id":"WTMKQ069CCJ7","country":"CN","nowtime":"2022-12-30 14:04:22"},"daily":[{"date":"2022-12-30","wind_scale":"2","humidity":"86"}],"last_update":"2022-12-30T08:00:00+08:00"}]}
image.png
image.png


tip:对于数组,我们需要先获取数组的子对象,然后再对子对象解析,不理解的可以看范例代码并结合展开图分析。

以上7条指令可以实现CJSON数据解析出需要字符串/数值等等(一般用于解析服务器下发数据),以下指令实现将字符串/数值等等打包成CJSON格式(一般用于向服务器发送数据)。

8. 创建cJSON对象
image.png
    cJSON *obj=cJSON_CreateObject();//创建一个对象
    cJSON *obj=cJSON_CreateArray();//创建一个数组
    创建一个CJSON对象,可以作为根节点或者子节点。
    创建一个CJSON对象数组,可以将对象插入数组中一般都是由一个object作为根节点来使用,array和object可以互相作为item互为子节点。

9. 创建数组
image.png
    cJSON *obj=cJSON_CreateIntArray(buf,5);//创建一个整型数组
    cJSON *obj=cJSON_CreateDoubleArray(buf,5);//创建一个双浮点型数组
    这两条指令用于创建整形数组/双浮点数组。buf:为相应类型的数组.
    例如添加整形数组 :
image.png
    int list2[4] = {5,6,7,8};
    cJSON *obj=cJSON_CreateObject();
    cJSON *obj_list=cJSON_CreateIntArray(list2,4);
    在通过添加项目图形块链接
    cJSON_AddItemToObject(obj,"lists",obj_list);
    结果:
image.png
   
10. 添加字符串/数字/逻辑值到对象中
image.png
cJSON_AddStringToObject(obj,"key","value");
cJSON_AddNumberToObject(obj,"key",5);
cJSON_AddTrueToObject(obj,"key");
cJSON_AddFalseToObject(obj,"key");
    这四条指令用于向对象中添加数据。
例如:
image.png
  cJSON *obj=cJSON_CreateObject();
  cJSON_AddStringToObject(obj,"name","xiaoming");
  cJSON_AddNumberToObject(obj,"age",15);
  cJSON_AddTrueToObject(obj,"status_on");
  cJSON_AddFalseToObject(obj,"status_off");
image.png
11. 添加项目(对象/数组)到对象中、添加对象到数组中

  cJSON_AddItemToObject(obj2,"key",obj1);
  cJSON_AddItemToArray(arr,obj);

     这两条指令用于向对象/数组中添加项目。array和object可以互相作为item互为子节点。
image.png
    cJSON *obj=cJSON_CreateObject();
    cJSON *results=cJSON_CreateArray();
    cJSON *location=cJSON_CreateObject();
    cJSON *last_update=cJSON_CreateObject();
    cJSON *daily=cJSON_CreateArray();
    cJSON *daily_temp=cJSON_CreateObject();

    cJSON_AddStringToObject(location,"id","WTMKQ069CCJ7");
    cJSON_AddStringToObject(location,"name","\u676d\u5dde");
    cJSON_AddStringToObject(location,"country","CN");
    cJSON_AddStringToObject(location,"nowtime","2022-12-30 14:04:22");
    cJSON_AddItemToArray(results,location);

    cJSON_AddStringToObject(daily_temp,"date","2022-12-30 14:04:22");
    cJSON_AddNumberToObject(daily_temp,"high",8);
    cJSON_AddNumberToObject(daily_temp,"humidity",86);
    cJSON_AddItemToArray(daily,daily_temp);
    cJSON_AddItemToArray(results,daily);

    cJSON_AddStringToObject(last_update,"last_update","2022-12-30T08:00:00+08:00");
    cJSON_AddItemToArray(results,last_update);

    cJSON_AddItemToObject(obj,"results",results);

结果:
image.png
3-范例代码-ASRPRO
image.png






image.png

CJSON范例.zip

5.24 KB, 下载次数: 0

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|好好搭搭在线 ( © 好好搭搭在线 浙ICP备19030393号-1 )

GMT+8, 2024-5-1 23:04 , Processed in 0.352081 second(s), 25 queries .

Powered by Discuz!

© 2001-2024 Comsenz Inc.

快速回复 返回顶部 返回列表