json文件与cJSON库的使用
json数据文件是项目中很常见的一类数据文件,JSON全称 “JavaScript Object Notation”,下面将对json数据文件进行介绍。
1、 json数据格式
JSON有2种结构形式,键值对形式和数组形式。常采用键值对形式。
JSON键值对形式举例,如下:
"person":
{
"name": "stuname",
"age": "24",
"sex": "man",
"hometown":
{
"province": "anhui",
"city": "anqing",
"county": "qianshan"
}
}
}
这种结构的JSON数据规则是:一个无序的“‘名称/值’对”集合。一个对象以 {左括号 开始, }右括号 结束。每个“名称”后跟一个 :冒号 ;“‘名称/值’ 对”之间使用 ,逗号 分隔。
JSON数组形式举例,如下:
["stuname", 24, "man", "anhui anqing qianshan"]
2、cJSON结构体
这里有个很重要的结构体是需要用到的就是
cJSON 结构体如下:
typedef struct cJSON
{
struct cJSON *next,*prev; /* 遍历数组或对象链的前向或后向链表指针*/
struct cJSON *child; /*数组或对象的孩子节点*/
int type; /* key的类型*/
char *valuestring; /*字符串值*/
int valueint; /* 整数值*/
double valuedouble; /* 浮点数值*/
char *string; /* key的名字*/
} cJSON;
说明:
- cJSON是使用链表来存储数据的,其访问方式很像一颗树。每一个节点可以有兄弟节点,通过next/prev指针来查找,它类似双向链表;每个节点也可以有孩子节点,通过child指针来访问,进入下一层。只有节点是对象或数组时才可以有孩子节点。
- type是键(key)的类型,一共有7种取值,分别是:False,Ture,NULL,Number,String,Array,Object。若是Number类型,则valueint或valuedouble中存储着值。若期望的是int,则访问valueint,若期望的是double,则访问valuedouble,可以得到值。若是String类型的,则valuestring中存储着值,可以访问valuestring得到值。
- string中存放的是这个节点的名字,可理解为key的名称。
3、使用cJSON解析json数据
注:自己使用时可以只需要其中的cJSON.c和cJSON.h文件就可以了,只需要将cJSON和自己的main文件一起编译即可。
- cJSON *cJSON_Parse(const char *value);
- 功能:解析JSON数据包,并按照cJSON结构体的结构序列化整个数据包。可以看做是获取一个句柄。
- 参数:value - - 待解析json句柄
- cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
- 功能:获取json指定的对象成员
- 参数:
*objec - - 第一个函数中获取的句柄。
string - - 需要获取的对象 - 返回值:这个对象成员的句柄
如果json格式的对象成员直接就是字符串那么就可以直接通过结构体中的valuestring元素来获取这个成员的值
- cJSON *cJSON_GetArrayItem(cJSON *array,int item);
-
功能:有可能第二个函数中获取到的是成员对象值是一个数组,那么就需要用到这个函数。用来获取这个数组指定的下标对象
-
参数:
*array - - 传入第二步中返回的值
item - - 想要获取这个数组的下标元素 -
返回值:这个数组中指定下标的对象。然后在对这个返回值重复使用第二步函数就可以获取到各个成员的值了。也就是说对象是数组的比是字符串的要多用一个cJSON_GetArrayItem函数,其他的没区别。
- cJSON_Delete(cJSON *object)
- 功能:用来释放你第一步获取的句柄,来释放整个内存。用在解析完后调用
示例:
1 #include <stdio.h>
2 #include "cJSON.h"
3
4 int main() {
5 FILE *fp = NULL;
6 cJSON *json;
7 char *out;
8 char line[1024] = {0
9};
10 if(NULL != (fp = fopen("./test.ply", "r"))) {
11 while (NULL != fgets(line, sizeof(line), fp)) {
12 json=cJSON_Parse(line); //获取整个大的句柄
13 out=cJSON_Print(json); //这个是可以输出的。为获取的整个json的值
14 cJSON *arrayItem = cJSON_GetObjectItem(json,"syslog_db"); //获取这个对象成员
15 cJSON *object = cJSON_GetArrayItem(arrayItem,0); //因为这个对象是个数组获取,且只有一个元素所以写下标为0获取
16
17 /*下面就是可以重复使用cJSON_GetObjectItem来获取每个成员的值了*/
18 cJSON *item = cJSON_GetObjectItem(object,"db_user"); //
19 printf("db_user:%s\n",item->valuestring);
20
21 item = cJSON_GetObjectItem(object,"db_password");
22 printf("db_password:%s\n",item->valuestring);
23
24 item = cJSON_GetObjectItem(object,"db_type");
25 printf("db_type:%s\n",item->valuestring);
26
27 item = cJSON_GetObjectItem(object,"db_ip");
28 printf("db_ip:%s\n",item->valuestring);
29
30 item = cJSON_GetObjectItem(object,"db_port");
31 printf("db_port:%s\n",item->valuestring);
32
33 item = cJSON_GetObjectItem(object,"db_name");
34 printf("db_name:%s\n",item->valuestring);
35
36 item = cJSON_GetObjectItem(object,"sql");
37 printf("db_sql:%s\n",item->valuestring);
38
39
40 /*这里这个是直接可以获取值的*/
41 arrayItem = cJSON_GetObjectItem(json,"syslog_enable");
42 printf("%s\n",arrayItem->valuestring);
43 }
44 }
45 cJSON_Delete(json);
46 close(fp);
47 }
4、使用cJSON创建JSON数据
创建一个键值对
首先是一个简单的键值对字符串,要生成的目标如下:{“firstName”:“Brett”}
要进行创建,就是先确定键与值,然后转为cJSON格式。
我们很容易就能明确键为firstName,值为Brett,可是,使用cJSON怎么创建呢?
对于这个简单的例子,我们只需要调用下面cJSON常用函数的其中五个接口函数就可以实现创建了。
cJSON常用函数:
//创建json对象(根对象、成员对象)
cJSON* cJSON_CreateObject();
//创建 字符串 类型cjson数据项
cJSON* cJSON_CreateString(const char *string);
//创建 数字 类型cjson数据项
cJSON *cJSON_CreateNumber(double num);
//创建json对象(数组对象)
cJSON* cJSON_CreateArray(void);
//添加json对象到json数组对象
void cJSON_AddItemToArray(cJSON *array, cJSON*item);
//添加json数据项到json对象
void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
//删除json对象
void cJSON_Delete(cJSON *c);
//打印json对象的内容,注该函数内部分配内存,使用完成后需要使free()释放内存。
char* cJSON_Print(cJSON *item);
示例:创建{“firstName”:“Brett”}
(1)首先调用cJSON_ CreateObject()函数,创建一个JSON对象,之后便可向这个对象中添加string或int等内容的数据项了。//使用该函数会通过malloc()函数在内存中开辟一个空间,使用完成需要手动释放。
cJSON* root=cJSON_CreateObject();
(2)调用cJSON_CreateString ()函数,由一个字符串生成一个cJSON的数据项。
cJSON* item=cJSON_CreateString("Brett");
(3)将上一步生成的数据项与其键值(“firstName”)一起添加到root对象中。
cJSON_AddItemToObject(root,"firstName",item);
其实到这一步,我们在内存中的cJSON对象就已经构建完成了,后面是展示结果了。
(4)将cJSON对象的内容解析为字符串,并展示出来。
out=cJSON_Print(root);
printf("out:%s\n",out);
(5)通过cJSON_Delete(),释放cJSON_CreateObject ()分配出来的内存空间。
cJSON_Delete(root);
(6)释放cJSON_Print ()分配出来的内存空间。
free(out);
这样就完成了一次cJSON接口调用,实现了字符串的创建工作。
如下图所示是基于MQTT协议的一个模型注册示例:
void Ope_DeviceModel(struct mosquitto *mosq, t_TemDEVICE* ptempar)
{
char Topic[255];
cJSON* root;
cJSON* body;
char* pMsg = NULL;
char JsonCurrentTime[32];
cJSON* body_root;
strcpy(InitModel.type,"float");
strcpy(InitModel.unit,"v");
strcpy(InitModel.deadzone,"0.5");
strcpy(InitModel.ratio,"1");
strcpy(InitModel.isReport,"1");
strcpy(InitModel.userdefine,"no");
memset(Topic,'\0',sizeof(Topic));
strcpy(Topic,Topic_Set_Model);
root = cJSON_CreateObject();
cJSON_AddItemToObject(root,"token",
cJSON_CreateString("200513"));
memset(JsonCurrentTime,'\0',sizeof(JsonCurrentTime));
GetCurrentJsonTime(JsonCurrentTime);
cJSON_AddItemToObject(root, "timestamp", JSON_CreateString(JsonCurrentTime));
cJSON_AddItemToObject(root, "model", cJSON_CreateString(ptempar->model));
//body = cJSON_AddArrayToObject(root, "body");
body = cJSON_CreateArray();
cJSON_AddItemToObject(root, "body",body);
body_root = cJSON_CreateObject();
cJSON_AddItemToObject(body_root, "name", cJSON_CreateString(ptempar->Tem_param->name));
cJSON_AddItemToObject(body_root, "type", cJSON_CreateString(InitModel.type));
cJSON_AddItemToObject(body_root, "unit", cJSON_CreateString(InitModel.unit));
cJSON_AddItemToObject(body_root, "deadzone", cJSON_CreateString(InitModel.deadzone));
cJSON_AddItemToObject(body_root, "ratio", cJSON_CreateString(InitModel.ratio));
cJSON_AddItemToObject(body_root, "isReport", cJSON_CreateString(InitModel.isReport));
cJSON_AddItemToObject(body_root, "userdefine", cJSON_CreateString(InitModel.userdefine));
cJSON_AddItemToArray(body, body_root);
pMsg = cJSON_Print(root);
printf("register model Json=%s! \n",pMsg);
Mosq_Send(mosq,Topic,pMsg,strlen(pMsg));
free(pMsg);
cJSON_Delete(root);
}