文章目录
- 写在前面
- 一、安装cJSON
- 二、使用cJSON
- 1、使用的文件
- 2、如何传输数据:****
- 三、JSON语法
- 四、cJSON函数讲解
- 1、cJSON结构体 **
- 2、cJSON结构体与字符串之间的转换(重要)
- 2.1、标题将cJSON结构体转换为字符串(常用)
- 2.2、将字符串转为cJSON结构体(常用)
- 3、cJSON创建键值对
- 3.1、先调用 cJSON_CreateXXX 创建对象或数组,然后调用 cJSON_AddItemToObject 将值加入到对象或数组中
- 3.2、直接调用 cJSON_AddXXXToObject 创建并添加值到对象中
- 4、解析
- 5、释放cJSON数据
- 五、示例
- 1、创建
- 2、解析(主要参考与使用)
- 2.1、解析 {}
- 2.2、解析[ {} {} ]
- 3、解析(参考形式)
- 3.1、解析 {}
- 3.2、解析 [ ]
- 3.3、解析 [ {} {} ]
- 3.4、解析[ [ ] [ ] ]
- 3.5、解析 { { } { } }
- 参考文章
写在前面
什么是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、解析 {}
{
/*************** 方式一 ***************/
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、解析 [ ]
{
/*************** 方式一 ***************/
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、解析 [ {} {} ]
{
/*************** 方式一 ***************/
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、解析[ [ ] [ ] ]
{
/*************** 方式一 ***************/
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、解析 { { } { } }
{
/*************** 方式一 ***************/
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格式文件(创建、插入、解析、修改、删除)