JSON数据格式讲解与cJSON库的使用

写在前面

什么是JSON:一种轻量级的数据交换格式
JSON用途:解析收到的数据和发送对方能够解析的数据
什么是cJSON:c语言格式下使用JSON的工具

一、安装cJSON

cjson官方库,直接点击下载zip,解压缩

git clone https://github.com/DaveGamble/cJSON.git
cd cJSON/
mkdir build
cd build/
cmake ..
make
make install

二、使用cJSON

1、使用的文件

然后我们,可以看到很多文件,但是,我们不需要这么多,使用cjson只需要两个文件,
拷贝cJSON.c和cJSON.h文件到自己的项目中就可以了,linux,windows上都可以使用

CJOSN.h
CJSON.c

2、如何传输数据:****

1、创建cJSON格式数据,转换成为cJSON字符串,然后传输。
2、将cJSON字符串解析成cJSON格式数据,然后提取出相应的数据内容。

三、JSON语法

JSON对象是一个无序的"key(关键字)/value(值)"键值对的集合:
"{“开始,以”}“结束 ,允许嵌套使用
每个key(关键字)和value(值)成对出现,关键字和值之间使用”:“分隔
键/值之间用”,"分隔
在这些字符前后允许存在无意义的空白符

其中**关键字**
			只能是字符串(使用双引号“”表示)


****可以有如下表示:
					数字(整数或浮点数)
					字符串(在双引号中)
					逻辑值(true 或 false)
					数组 (在中括号中)
					对象 (在大括号中)
					null

四、cJSON函数讲解

1、cJSON结构体 **

/* The cJSON structure: */
typedef struct cJSON
{
//这些不用管
    struct cJSON *next;
    struct cJSON *prev;
    struct cJSON *child;

//这些都要知道
    //该json对象的类型,可以是字符串,int,double....
    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,那么值存在这里
    int valueint;
    /* The item's number, if type==cJSON_Number */
    //如果类型是double,那么值存在这里
    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;

2、cJSON结构体与字符串之间的转换(重要)

2.1、标题将cJSON结构体转换为字符串(常用)

使用这个两个函数一定一定一定要 调用cJSON_Delete函数 释放它们返回的指针内存

//将CJSON数据转换为字符串(保留原来的格式:例如会保留空格和回车)
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
//将CJSON数据转换为字符串(删除所有格式,只保留文本)
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);

2.2、将字符串转为cJSON结构体(常用)

//将json字符串转换为结构体,并且将其赋给一个指针
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);

3、cJSON创建键值对

3.1、先调用 cJSON_CreateXXX 创建对象或数组,然后调用 cJSON_AddItemToObject 将值加入到对象或数组中

CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);	//创建对象---常用
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);	//创建数组---常用
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);//创建整型数组
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);//创建双浮点型数组

CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);	//在对象中添加项目
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);//在数组中添加项目

3.2、直接调用 cJSON_AddXXXToObject 创建并添加值到对象中

CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);

4、解析

注意:解析—是从cJSON结构体类型中—解析

//获取数组大小
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
//获取数组里面的某一个值
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
//这个函数将某一个键值对,提取出来放到一个结构体中
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)

5、释放cJSON数据

void  cJSON_Delete(cJSON *c);
/*作用:释放位于堆中cJSON结构体内存

五、示例

1、创建

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

int main(void)
{
	double  grade[4]={66.51,118.52,61.53,128.54};
	int		time[4]={123,456,789,150};
	
	cJSON *TCP = cJSON_CreateObject();				//创建一个对象
	
 	cJSON_AddStringToObject(TCP,"name","MQ");		//添加字符串 
	cJSON_AddNumberToObject(TCP,"age",25);	    	//添加整型数字 
	cJSON_AddNumberToObject(TCP,"height",183.52);	//添加浮点型数字
	cJSON_AddFalseToObject(TCP,"gender");			//添加逻辑值false
	 
	cJSON *ADD	= cJSON_CreateObject();				//创建一个对象
	cJSON_AddStringToObject(ADD,"country","China");	//添加字符串 
	cJSON_AddNumberToObject(ADD,"zip-code",123456);	//添加整型数字
	cJSON_AddItemToObject(TCP,"address",ADD);
 	
	cJSON *SUB  = cJSON_CreateArray();				//创建一个数组
	cJSON_AddStringToObject(SUB,"","政治"); 		//添加字符串到数组
 	cJSON_AddStringToObject(SUB,"","数学");
	cJSON_AddStringToObject(SUB,"","英语");
	cJSON_AddStringToObject(SUB,"","专业课");
	cJSON_AddItemToObject(TCP,"subject",SUB);		//添加数组到对象
	
	cJSON *TIM  = cJSON_CreateIntArray(time,4);		//创建一个整型数组
	cJSON_AddItemToObject(TCP,"time",TIM);
	
	cJSON *GRA  = cJSON_CreateDoubleArray(grade,4);	//创建一个双浮点型数组
	cJSON_AddItemToObject(TCP,"grade",GRA);
	
	cJSON *STU  = cJSON_CreateArray();			//创建一个数组
	
	cJSON *Z3  = cJSON_CreateObject();			//创建一个对象
	cJSON_AddStringToObject(Z3,"name","张三");	//添加字符串 
	cJSON_AddNumberToObject(Z3,"age",24);	    //添加整型数字 
	cJSON_AddTrueToObject(Z3,"gender");			//添加逻辑值 
	cJSON_AddItemToArray(STU,Z3);				//添加对象到数组中 
	
	cJSON *L4  = cJSON_CreateObject();			//创建一个对象
	cJSON_AddStringToObject(L4,"name","李四");	//添加字符串 
	cJSON_AddNumberToObject(L4,"age",25);	    //添加整型数字 
	cJSON_AddTrueToObject(L4,"gender");			//添加逻辑值 
	cJSON_AddItemToArray(STU,L4);				//添加对象到数组中
	
	cJSON *W5  = cJSON_CreateObject();			//创建一个对象
	cJSON_AddStringToObject(W5,"name","王五");	//添加字符串 
	cJSON_AddNumberToObject(W5,"age",26);	    //添加整型数字 
	cJSON_AddTrueToObject(W5,"gender");			//添加逻辑值 
	cJSON_AddItemToArray(STU,W5);				//添加对象到数组中
	
	cJSON_AddItemToObject(TCP,"student",STU);	//添加数组到对象中

	char *json_data = cJSON_Print(TCP);	//JSON数据结构转换为JSON字符串
	printf("%s\n",json_data);//输出字符串
	cJSON_Delete(TCP);//清除结构体
	return 0;
}

现象

{
	"name":	"MQ",
	"age":	25,
	"height":	183.52,
	"gender":	false,
	"address":	{
		"country":	"China",
		"zip-code":	123456
	},
	"subject":	["政治", "数学", "英语", "专业课"],
	"time":	[123, 456, 789, 150],
	"grade":	[66.51, 118.52, 61.53, 128.54],
	"student":	[{
			"name":	"张三",
			"age":	24,
			"gender":	true
		}, {
			"name":	"李四",
			"age":	25,
			"gender":	true
		}, {
			"name":	"王五",
			"age":	26,
			"gender":	true
		}]
}

2、解析(主要参考与使用)

2.1、解析 {}

int parsecjson_data(char *jsonstring)
{	
	cJSON *cjson= cJSON_Parse(jsonstring);
	if(cjson) 
	{
		//解析 JSON 数据并处理
		cJSON *state = cJSON_GetObjectItem(cjson, "state");
		if (state != NULL && cJSON_IsString(state)) {
			printf("State: %s\n", state->valuestring);		//字符串
		}

		cJSON *brightness = cJSON_GetObjectItem(cjson, "brightness");
		if (brightness != NULL && cJSON_IsNumber(brightness)) {
			printf("Brightness: %d\n", brightness->valueint);		//整形
		}
		
		cJSON *height = cJSON_GetObjectItem(object2, "height");  
		if (height != NULL && cJSON_IsNumber(height)) {
			printf("height: %d \n", height->valuedouble);			//浮点型
		}
		
		cJSON *gender = cJSON_GetObjectItem(object2, "gender");  
		if (gender != NULL && cJSON_IsBool(gender)) {
			printf("gender: %d \n", gender->type);			//布尔类型	true/false
		}
	}
	cJSON_Delete(cjson);
	return 0;
}

2.2、解析[ {} {} ]

int parsecjson_data(char *jsonstring)
{	
	cJSON *cjson = cJSON_Parse(jsonstring);
	
	if (cjson != NULL && cJSON_IsArray(cjson)) {
		
			int array_size = cJSON_GetArraySize(cjson);
			if (array_size >= 2) {
				cJSON *object1 = cJSON_GetArrayItem(cjson, 0);  // 获取数组中的第一个对象
				cJSON *object2 = cJSON_GetArrayItem(cjson, 1);  // 获取数组中的第二个对象
				
				if (object1 != NULL && cJSON_IsObject(object1)) {		// 第一个对象中的字段
				
					cJSON *sens1 = cJSON_GetObjectItem(object2, "K3");  // 第一个对象中有名为 K3 的字段
					if (sens1 != NULL && cJSON_IsNumber(sens1)) {
						car.sens1 = sens1->valueint;
						printf("sens1: %d \n", sens1->valueint);
					}
				} 
				
				if (object2 != NULL && cJSON_IsObject(object2)) {
					
					cJSON *sens2 = cJSON_GetObjectItem(object2, "K4");  // 第二个对象中有名为 K4 的字段
					if (sens2 != NULL && cJSON_IsNumber(sens2)) {
						car.sens2 = sens2->valueint;
						printf("sens2: %d\n", sens2->valueint);
					}
				}
			}
		}
	cJSON_Delete(cjson);
	return 0;
}

3、解析(参考形式)

注释:借鉴参考文章

3.1、解析 {}

1

{
	/*************** 方式一 ***************/
	item = cJSON_GetObjectItem(root, "interest");		// 获取object对象名
	if (item != NULL) {
		cJSON *val = NULL;

		val = cJSON_GetObjectItem(item, "basketball");	// 根据object对象名获得里面的basketball数据
		if (val != NULL && val->type == cJSON_String) {
			v_str = val->valuestring;
			printf("basketball = %s\n", v_str);
		}

		val = cJSON_GetObjectItem(item, "badminton");	// 根据object对象名获得里面的badminton数据
		if (val != NULL && val->type == cJSON_String) {
			v_str = val->valuestring;
			printf("badminton = %s\n", v_str);
		}
	}

	/*************** 方式二 ***************/
	item = cJSON_GetObjectItem(root, "interest");
	if (item != NULL) {
		cJSON *obj = item->child;	// 获得 "basketball":	"篮球"

		while (obj) {
			if (obj->type == cJSON_String) {
				char *v_str = obj->valuestring;
				printf("%s = %s\n", obj->string, v_str);	// 可以通过string获得键
			}
			// 获取下一个元素
			obj = obj->next;
		}
	}
}

3.2、解析 [ ]

2

{
	/*************** 方式一 ***************/
	item = cJSON_GetObjectItem(root, "color");
	if (item != NULL) {
		int size = cJSON_GetArraySize(item);	// 获得数组个数

		for (int i = 0; i < size; i++) {
			cJSON *arr = cJSON_GetArrayItem(item, i);	// 根据索引获得数组中的值

			if (arr != NULL && arr->type == cJSON_String) {
				v_str = arr->valuestring;
				printf("color = %s\n", v_str);
			}
		}
	}


	/*************** 方式二 ***************/
	item = cJSON_GetObjectItem(root, "color");
	if (item != NULL) {
		cJSON *arr = item->child;	// 获得 "black"

		while (arr) {
			if (arr->type == cJSON_String) {
				char *v_str = arr->valuestring;
				printf("color = %s\n", v_str);
			}
			// 获取下一个元素
			arr = arr->next;
		}
	}
}

3.3、解析 [ {} {} ]

3

{
	/*************** 方式一 ***************/
	item = cJSON_GetObjectItem(root, "like");
	if (item != NULL) {
		int size = cJSON_GetArraySize(item);	// 获取的数组大小

		for (int i = 0; i < size; i++) {
			cJSON *obj = cJSON_GetArrayItem(item, i);		// 获取的数组里的obj
			cJSON *val = NULL;

			if (obj != NULL && obj->type == cJSON_Object) {	// 判断数字内的元素是不是obj类型
				val = cJSON_GetObjectItem(obj, "game");		// 获得obj里的值

				if (val != NULL && val->type == cJSON_String) {
					v_str = val->valuestring;
					printf("game = %s\n", v_str);
				}

				val = cJSON_GetObjectItem(obj, "price");
				if (val != NULL && val->type == cJSON_Number) {
					v_double = val->valuedouble;
					printf("price = %.2f\n", v_double);
				}
			}
		}
	}


	/*************** 方式二 ***************/
	item = cJSON_GetObjectItem(root, "like");
	if (item != NULL) {
		cJSON *obj = item->child;	// 获得 { "game": "马里奥", "price": 66.6 }

		while (obj) {
			if (obj->type == cJSON_Object) {

				cJSON *objValue = obj->child;	// 获得 "game": "马里奥"
				while (objValue) {

					// 再通过类型去区分
					if (objValue->type == cJSON_String) {
						char *v_str = objValue->valuestring;
						printf("%s = %s\n", objValue->string, v_str);

					} else if (objValue->type == cJSON_Number) {
						double v_double = objValue->valuedouble;
						printf("%s = %.2f\n", objValue->string, v_double);
					}
					// 获取下一个元素
					objValue = objValue->next;
				}
			}
			// 获取下一组元素
			obj = obj->next;
		}
	}
}

3.4、解析[ [ ] [ ] ]

4

{
	/*************** 方式一 ***************/
	item = cJSON_GetObjectItem(root, "education");
	if (item != NULL) {
		int size = cJSON_GetArraySize(item);	// 获取的数组大小

		for (int i = 0; i < size; i++) {
			cJSON *arr = cJSON_GetArrayItem(item, i);		// 解析获得	[ "小学", "初中" ]

			if (arr != NULL && arr->type == cJSON_Array) {
				int arrSize = cJSON_GetArraySize(arr);

				for (int j = 0; j < arrSize; j++) {
					cJSON *arr2 = cJSON_GetArrayItem(arr, j);	// 再进一步解析就可以得到数组里面的元素了

					if (arr2 != NULL && arr2->type == cJSON_String) {
						v_str = arr2->valuestring;
						printf("education = %s\n", v_str);
					}
				}
			}
		}
	}

	/*************** 方式二 ***************/
	item = cJSON_GetObjectItem(root, "education");
	if (item != NULL) {
		cJSON *arr = item->child;	// 获得 [ "小学", "初中" ]

		while (arr) {
			if (arr->type == cJSON_Array) {
			
				cJSON *arrValue = arr->child;	// 获得 "小学"
				while (arrValue) {
					if (arrValue->type == cJSON_String) {
						char *v_str = arrValue->valuestring;
						printf("education = %s\n", v_str);
					}
					arrValue = arrValue->next;	// 获取下一个元素
				}
			}
			// 获取下一组
			arr = arr->next;
		}
	}
}

3.5、解析 { { } { } }

5

{
	/*************** 方式一 ***************/
	char *arrStr[] = { "serialOne", "serialTwo" };		// 可以提前定义需要解析的对象键,这样就可以使用for循环进行解析了

	item = cJSON_GetObjectItem(root, "languages");
	if (item != NULL) {
		cJSON *val = NULL;
		int size = sizeof(arrStr) / sizeof(char *);

		// 通过遍历指针数组,获得每个对象的键,在进行解析操作(如果不使用for循环解析,那就老老实实的写代码将全部个数解析完毕)
		for (int i = 0; i < size; i++) {
			cJSON *obj1 = cJSON_GetObjectItem(item, arrStr[i]);

			if (obj1 != NULL && obj1->type == cJSON_Object) {

				val = cJSON_GetObjectItem(obj1, "language");
				if (val != NULL && val->type == cJSON_String) {
					v_str = val->valuestring;
					printf("education = %s\n", v_str);
				}

				val = cJSON_GetObjectItem(obj1, "grade");
				if (val != NULL && val->type == cJSON_Number) {
					v_int = val->valueint;
					printf("grade = %d\n", v_int);
				}
			}
		}
	}



	/*************** 方式二 ***************/
	// 在不知道键是什么的情况下 和 不知道有多少元素的情况下可用
	item = cJSON_GetObjectItem(root, "languages");
	if (item != NULL) {
		// 获取到languages里的第一个子元素
		cJSON *obj = item->child;	// 也就是:"serialOne": { "language": "汉语", "grade": 10 }

		while (obj) {
			if (obj->type == cJSON_Object) {

				// 获取到子元素的子元素
				cJSON *value = obj->child;	// 也就是:{ "language": "汉语", "grade": 10 }

				while (value) {
					if (value->type == cJSON_String) {
						printf("%s = %s\n", value->string, value->valuestring);

					} else if (value->type == cJSON_Number) {
						printf("%s = %d\n", value->string, value->valueint);
					}
					// 通过next可以自由获取里面的元素了
					value = value->next;
				}
			}

			// 获得下一组子元素
			obj = obj->next;
		}
	}
}

参考文章

cJSON库用法详解
Cjson入门快速使用
使用cjson库 操作Json格式文件(创建、插入、解析、修改、删除)

  • 30
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

好好睡觉好好吃饭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值