CJSON库的学习

目录

一、JSON简介

二、 JSON语法

​​​​​​三、 CJSON简介:

四、 CJSON数据结构

五、使用CJSON构造JSON

1. cJSON常用库函数介绍

2. CJSON构造JSON实例代码

(1)!!!编译过程中有两个注意的点:

3. 使用cJSON解析JSON实例代码


一、JSON简介

  1.  JSON(JavaScript object Notation),即JavaScript 对象符号,是一种轻量级的数据格式;【其本质就是字符串
  2.  它采用完全独立于编程语言的文本格式来存储和表示数据,语法简洁,层次结构清晰,易于人阅读和编写,同时也易于机器解析和生成,有效的提升了网络传送效率。
  3.  因为它完全独立于编程语言所以支持跨平台开发;
  4.  JSON 的名称中虽然带有JavaScript,但这是指其语法规则是参考JavaScript对象的,而不是指只能用于JavaScript 语言。
  5.  因为JSON本身就是参考JavaScript 对象的规则定义的,其语法与JavaScript定义对象的语法几乎完全相同。

二、 JSON语法

  1.  JSON可以将数据转换为字符串,接着在网络中或者程序里面传递这个字符串,最后可以还原成各个编程语言所支持的数据格式;
  2.  JSON是一个无序的键值对(key / value)集合;
    • JSON以"{“开始,以”}"结束,允许嵌套使用
    • 每个key(关键字)和value(值)成对出现,关键字和值之间使用":"分隔
    • 键/值对之间用","分隔
    • 在这些字符前后允许存在无意义的空白符
    • 数组(Array)用方括号(“[]”)表示。
    • 对象(0bject)用大括号(“{}”)表示。
    • 名称/值对(name/value)组合成数组和对象。
    • 名称(name)置于双引号中,值(value)有字符串、数值、布尔值、null、对象和数组。
    • 并列的数据之间用逗号(“,”)分隔
  • 在线的JSON解析网站如下:JSON解析

  • 如下是一个实际的例子,来体会一下JSON:

{
	"name": "JK",
	"age": 18,
	"height": 175,
	"sex": false,


	"address": {
		"country": "China",
		"tel": 123456
	},


	"subject": ["语文", "数学", "英语"],
	"grade": [1, 2, 3],


	"student": [{
			"name": "wsf",
			"age": 23,
			"sex": true
		},
		{
			"name": "rs",
			"age": 25,
			"sex": true
		}
	]
}

  • JSON树可视化

​​​​​​三、 CJSON简介:

  1. CJSON对象的实现采用了树形结构,每一个对象就是树的一个节点,每个节点由cJSON这个结构体组成,对象中的元素也由cJSON这个结构体组成。同一层的对象和元素是双向链表结构,由next和prev指针链接。不同层的对象或元素由child指针链接起来。type表示对象或元素类型,string表示对象或节点的名称。元素的值存储在valuestring, valueint和valuedouble中;

  2. cJSON是一个使用C语言编写的JSON数据解析器,具有超轻便,可移植,单文件的特点,使用MIT开源协议。

  3. 要使用CJSON,直接把项目从Github上clone下来,接着把CJSON.h,CJSON.c这两个源文件加入到工程中就行,使用时include CJSON.h头文件就行;

四、 CJSON数据结构

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

//逻辑值的宏定义
#define cJSON_Invalid (0)
#define cJSON_False  (1 << 0)
#define cJSON_True   (1 << 1)
#define cJSON_NULL   (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array  (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw    (1 << 7) /* raw json */


#define cJSON_IsReference 256
#define cJSON_StringIsConst 512


/* 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;


 
  
  1.  首先,CJSON不是将一整段JSON数据全抽象出来,而是将其中的一条JSON数据抽象出来,也就是一个键值对,用上面的结构体 strcut cJSON 来表示,其中用来存放值的成员列表如下:
    1. String:用于表示该键值对的名称;
    2. type:用于表示该键值对中值的类型;
    3. valuestring:如果键值类型(type)是字符串,则将该指针指向键值;
    4. valueint:如果键值类型(type)是整数,则将该指针指向键值;
    5. valuedouble:如果键值类型(type)是浮点数,则将该指针指向键值;
  2.  一段完整的JSON数据中由很多键值对组成,并且涉及到键值对的查找、删除、添加,所以使用链表来存储整段JSON数据,如上面的代码所示:
    1. next指针:指向下一个键值对
    2. prev指针指向上一个键值对
  3.  因为JSON数据支持嵌套,所以一个键值对的值会是一个新的JSON数据对象(一条新的链表),也有可能是一个数组,方便起见,在cJSON中,数组也表示为一个数组对象,用链表存储,所以:在键值对结构体中,当该键值对的值是一个嵌套的JSON数据或者一个数组时,由child指针指向该条新链表;
  4.  链表中的一些概念:
    1. 头指针:指向链表头结点的指针;
    2. 头结点:不存放有效数据,方便链表操作;
    3. 首节点:第一个存放有效数据的节点;
    4. 尾节点:最后一个存放有效数据的节点;

五、使用CJSON构造JSON

1. cJSON常用库函数介绍

extern cJSON *  cJSON_CreateObject(void);	//创建对象


extern cJSON *  cJSON_CreateArray(void);	//创建数组


extern cJSON *  cJSON_CreateIntArray(const int *numbers, int count);//创建整型数组


extern cJSON *  cJSON_CreateDoubleArray(const double *numbers, int count);//创建双浮点型数组


extern cJSON*  cJSON_AddNullToObject(cJSON * const object, const char * const name);//在对象中添加null


extern cJSON*  cJSON_AddTrueToObject(cJSON * const object, const char * const name);//在对象中添加true


extern cJSON*  cJSON_AddFalseToObject(cJSON * const object, const char * const name);//在对象中添加false


extern cJSON*  cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);//在对象中添加数字


extern cJSON*  cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);//在对象中添加字符串


extern cJSON_bool  cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);	//在对象中添加项目


extern cJSON_bool  cJSON_AddItemToArray(cJSON *array, cJSON *item);//在数组中添加项目


extern char *  cJSON_Print(const cJSON *item);//JSON数据结构转换为JSON字符串---有格式
extern char *  cJSON_PrintUnformatted(const cJSON *item);	//JSON数据结构转换为JSON字符串---无格式


extern void  cJSON_Delete(cJSON *item); //清除结构体


2. CJSON构造JSON实例代码

#include "string.h"
#include "cJSON.h"
#include "stdio.h"






int main()
{
    // 创建头指针
    cJSON *JSON_Root = NULL;


    // 创建头结点,并将头指针指向头结点(可以看做是一个树的根root)
    JSON_Root = cJSON_CreateObject();


    // 添加一条字符串类型的JSON数据
    cJSON_AddStringToObject(JSON_Root, "name", "zhuhua");


    // 添加一条浮点类型的JSON数据(添加一个链表结点)到root下
    cJSON_AddNumberToObject(JSON_Root, "height", 66.6666);


    // 添加一条整数型的JSON数据(链表结点)
    cJSON_AddNumberToObject(JSON_Root, "grade", 100);


    // 添加一个嵌套的JSON数据(添加一个链表节点, 又一个《对象》)
    cJSON *timeCode = cJSON_CreateObject();


    // true
    cJSON_AddTrueToObject(timeCode, "Sex");


    cJSON_AddStringToObject(timeCode, "datatime", "20220811");


    cJSON_AddFalseToObject(timeCode, "Judge");


    // 最后把这个对象加入到root下
    cJSON_AddItemToObject(JSON_Root, "TIMECODE", timeCode);


    // 再次嵌套,加入一个数组类型的JSON数据,在timecode结点之下(添加一个链表结点)
    cJSON *dataCode = cJSON_CreateArray();
    // 两种方式添加
    cJSON_AddStringToObject(dataCode, "", "English");


    cJSON_AddItemToArray(dataCode, cJSON_CreateString("zhuzhuzhu"));


    cJSON_AddStringToObject(dataCode, "", "huahuahua");


    cJSON_AddNumberToObject(dataCode, "number", 300);
    // 将datacode  (array)结点添加到timecode 对象结点下(同样数组也可以有对象数据, 甚至数组中数据类型也可以不一样,但这样理解上不太好)
    cJSON_AddItemToObject(timeCode, "DATACODE", dataCode);


    // 最后将JSON数据结构转换为字符串, 并且输出
    char *strForJson = cJSON_Print(JSON_Root);
    printf("json字符串:%s\n", strForJson);


    // 将字符串存入到文件中
    FILE *FCJ = NULL;
    FILE *FCJ1 = NULL;


    FCJ = fopen("data.txt", "w");
    FCJ1 = fopen("data1.txt", "w");


    int i = 0;
   
    for (i = 0; i < strlen(strForJson); ++i)
    {
        fprintf(FCJ, "%c", strForJson[i]);
        fputc(strForJson[i], FCJ1);
    }


    fclose(FCJ);
    fclose(FCJ1);


    // 清除结构体
    cJSON_Delete(JSON_Root);


    return 0;
}


  • 输出结果如下:

(1)!!!编译过程中有两个注意的点:

  1. 提示头文件中报unknown type name ‘size_t’错误:

    1. 原因及解决方案:

      1. 原因在测试c文件中加入了string.h的头文件,并且放在了cJSON.h的后面;

      2. 解决:一定要把string.h放在cJSON头文件的前面;

  2. 提示找不到pow和floor函数:

    1. 解决方案:需要链接math库libm(可以查一下libc相关)

  3. 编译语句

gcc cJson.c CJSONTest.c -o uim -lm
最后./uim执行即可;

3. 使用cJSON解析JSON实例代码

#include <stdio.h>
#include "cJSON.h"




int main()
{


    // 定义JSON字符串
    char json_string[]="{\"name\":\"zhuhua\",\
            \"height\":66.666600,\"grade\":100,\"TIMECODE\":{\"Sex\":true,\"datatime\":\"20220811\",\"Judge\":false,\"DATACODE\":[\"English\",\"zhuzhuzhu\",\"huahuahua\",300]}}";//定义JSON字符串	
    
    // 将JSON字符串转换成JSON结构体
    cJSON *JSON_ROOT = cJSON_Parse(json_string);


    // 判断转换是否成功
    if (JSON_ROOT == NULL)
    {
        printf("cjson error.......\n");
    }
    else
    {
        printf("%s\n", cJSON_Print(JSON_ROOT));
    }


    printf("提取数据\n");


    // 解析字符串 找key 得value
    char *name = cJSON_GetObjectItem(JSON_ROOT, "name")->valuestring;
    // 打印看一下效果
    printf("%s\n", name);


    double height = cJSON_GetObjectItem(JSON_ROOT, "height")->valuedouble;
    printf("%lf\n", height);


    int grade = cJSON_GetObjectItem(JSON_ROOT, "grade")->valueint;
    printf("%d\n", grade);


    // 对象和数组的接收
    cJSON *obj_timeCode = cJSON_GetObjectItem(JSON_ROOT, "TIMECODE");   // 解析对象


    cJSON *arr_dataCode = cJSON_GetObjectItem(obj_timeCode, "DATACODE");   // 解析数组      一层一层来


    int sex = cJSON_GetObjectItem(obj_timeCode, "Sex")->type;   // 解析逻辑值————输出逻辑值对应的宏定义数值
    printf("%d\n", sex);


    char *datatime = cJSON_GetObjectItem(obj_timeCode, "datatime")->valuestring;
    printf("%s\n", datatime);


    int judge = cJSON_GetObjectItem(obj_timeCode, "Judge")->type;   // 解析逻辑值————输出逻辑值对应的宏定义数值
    printf("%d\n", judge);


    // 数组的处理 先获取数组的成员个数
    int arr_size = cJSON_GetArraySize(arr_dataCode);
    printf("arrsize: %d\n", arr_size);
    int i = 0;
    for (i = 0; i < arr_size - 1; ++i)
    {
        printf("%s\n", cJSON_GetArrayItem(arr_dataCode, i)->valuestring);
    }
    printf("%d\n", cJSON_GetArrayItem(arr_dataCode, arr_size - 1)->valueint);


    // 清除结构体
    cJSON_Delete(JSON_ROOT);
    return 0;
}

  • 运行结果如下

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
cjson是一个轻量级的JSON解析器和生成器。它适用于嵌入式系统,特别是在FreeRTOS实时操作系统中使用。 cjson是一个简单且易于使用的,因此它在FreeRTOS中得到了广泛的应用。它提供了一组函数,可以将JSON字符串解析为一个C语言中的对象,或者将C语言对象转换为JSON字符串。这些功能非常有用,可以在嵌入式系统中处理JSON数据。 使用cjson,我们可以轻松地解析和生成JSON数据。例如,我们可以使用cjson将传感器数据以JSON格式发送到远程服务器。在服务器端,可以使用cjson将该JSON数据解析为对象,以便进行进一步的处理和分析。 另外,cjson还提供了一些功能,可以让我们在C语言中方便地访问JSON数据。例如,我们可以通过cjson获取JSON对象的键值对,或者在JSON数组中遍历元素。这些功能对于处理复杂的JSON数据结构非常有帮助。 在FreeRTOS中使用cjson并不复杂。我们只需要将cjson的源文件添加到FreeRTOS项目中,并在需要的地方包含相应的头文件。然后,我们就可以调用cjson中的函数来解析和生成JSON数据。 总之,cjson是一个非常实用的组件,它为嵌入式系统中处理JSON数据提供了便利。使用cjson,可以轻松地解析和生成JSON数据,并且可以方便地在C语言中访问JSON数据的各个部分。在FreeRTOS中使用cjson可以提高开发效率并简化代码实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值