一、什么是JSON
JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)。但它并不是编程语言,而是一种可以在服务器和客户端之间传输的轻量级数据交换格式。
二、JSON语法
2.1、JSON基本单元-键值对(key-value)
- 在JSON中,我们使用“键(key):值(value)”表示一组数据,键(key)使用字符串表示,并且是唯一的。键(key)可以简单理解为门牌号,而值(value)可以理解为房间里的内容。
- 键(key)和值(value)之间可以使用空格使排版更加美观;
- 值(value)的内容可以是字符串、数字、布尔类型等;
举个例子:
| { |
| "name": "张三", |
| "age" : 18, |
| "sex" : "男" |
| } |
复制
| { |
| "ClassName" : "电科一班", |
| “StudentsNum” : 12, |
| "StudentInfo" : |
| [ |
| { |
| "name": "张三", |
| "age" : 18, |
| "sex" : "男" |
| }, |
| { |
| "name": "李四", |
| "age" : 18, |
| "sex" : "女" |
| }, |
| ] |
| } |
复制
2.2、JSON对象和数组
- JSON对象使用“{}”表示,“{}”中的内容即为对象;
- JSON数组使用“[]”表示,“[]”中的内容即为数组;
| { |
| "Name" : "张三", |
| "IDInfo": |
| [ |
| "Nation": "中国", |
| "Age" : 18, |
| "Sex" : "男" |
| ] |
| |
| } |
复制
三、CJSON的使用
3.1、CJSON的结构:
| |
| typedef struct cJSON { |
| struct cJSON *next,*prev; |
| struct cJSON *child; |
| |
| int type; |
| |
| char *valuestring; |
| int valueint; |
| double valuedouble; |
| |
| char *string; |
| } cJSON; |
复制
结构体中的type表示JSON的类型,主要有6种:
- cJSON_False 0 表示JSON初始化为“flase”或者键(key)对应的值(value)为“false”
- cJSON_True 1 表示JSON初始化为“true”或者键(key)对应的值(value)为“true”
- cJSON_NULL 2 表示JSON初始化为“null”或者键(key)对应的值(value)为“null”
- cJSON_Number 3 数据类型为数字
- cJSON_String 4 数据类型为字符串
- cJSON_Array 5 数据类型为数组
- cJSON_Object 6 数据类型为JSON,表示还可以进一步解析
3.2、解析简单的JSON数据
- CJSON中解析相关的函数主要有两个:cJSON_Parse和cJSON_GetObjectItem,前者用于将JSON格式的数据转换成CJSON格式中对应的结构,后者用于获取JSON的键值对的内容。
- CJSON中,有三个特殊值的数据类型,“true”、“false”和“null”,这三个类型,在作为值(value)时,可以不使用双引号
一个简单的例子:
| int MyTest() |
| { |
| char *json_str = NULL; |
| cJSON *cjson_str = NULL; |
| cJSON *cjson_data = NULL; |
| json_str = "{\"name\": \"zhangsan\", \"age\":18, \"grade\":98.5}"; |
| cjson_data = cJSON_Parse(json_str); |
| printf("%d\r\n",cjson_data->type); |
| if(cjson_data) |
| { |
| cjson_str = cJSON_GetObjectItem(cjson_data,"name"); |
| if(cjson_str)printf("%s:%s type=%d\r\n",cjson_str->string,cjson_str->valuestring, cjson_str->type); |
| cjson_str = cJSON_GetObjectItem(cjson_data,"age"); |
| if(cjson_str)printf("%s:%d type=%d\r\n",cjson_str->string,cjson_str->valueint, cjson_str->type); |
| cjson_str = cJSON_GetObjectItem(cjson_data,"grade"); |
| if(cjson_str)printf("%s:%.2f type=%d\r\n",cjson_str->string,cjson_str->valuedouble, cjson_str->type); |
| cJSON_Delete(cjson_data); |
| } |
| } |
复制
输出结果:
| 6 |
| name:zhangsan type=4 |
| age:18 type=3 |
| grade:98.50 type=3 |
复制
复杂点的例子:
| int MyTest2() |
| { |
| char *str = NULL; |
| char *json_str = NULL; |
| cJSON *cjson_str = NULL; |
| cJSON *cjson_data = NULL; |
| json_str = "{ \ |
| \"personA\":{\"name\":\"james\",\"pass\":false,\"age\":20}, \ |
| \"personB\":{\"name\":\"joe\",\"pass\":true,\"age\":18} \ |
| }"; |
| int arr_size; |
| |
| cjson_data = cJSON_Parse(json_str); |
| |
| if(!cjson_data) |
| { |
| printf("json phase error\r\n"); |
| return -1; |
| } |
| printf("%d\r\n",cjson_data->type); |
| |
| cJSON* personA = cJSON_GetObjectItem(cjson_data,"personA");; |
| |
| if(personA) |
| { |
| cjson_str = cJSON_GetObjectItem(personA,"name"); |
| if(cjson_str)printf("%s:%s type=%d\r\n",cjson_str->string,cjson_str->valuestring, cjson_str->type); |
| cjson_str = cJSON_GetObjectItem(personA,"age"); |
| if(cjson_str)printf("%s:%d type=%d\r\n",cjson_str->string,cjson_str->valueint, cjson_str->type); |
| cjson_str = cJSON_GetObjectItem(personA,"pass"); |
| if(cjson_str)printf("%s:%.2f type=%d\r\n",cjson_str->string,cjson_str->valuedouble, cjson_str->type); |
| cJSON_Delete(cjson_data); |
| } |
| else |
| { |
| printf("personA phase error\r\n"); |
| } |
| return 0; |
| } |
复制
输出结果:
| 6 |
| name:james type=4 |
| age:20 type=3 |
| pass:0.00 type=0 |
复制
由于JSON结构体中存在字符串类型、浮点型和整型三种数据类型,为了方便用户处理,CJSON提供了cJSON_Print,统一将JSON解析的结果转换成字符串类型
| int MyTest3() |
| { |
| char *str; |
| char *json_str; |
| cJSON *cjson_data; |
| json_str = "{ \ |
| \"personA\":{\"name\":\"james\",\"sex\":\"boy\",\"age\":20}, \ |
| \"personB\":{\"name\":\"joe\",\"sex\":\"girl\",\"age\":18} \ |
| }"; |
| int arr_size; |
| |
| cjson_data = cJSON_Parse(json_str); |
| |
| if(!cjson_data) |
| { |
| printf("json phase error\r\n"); |
| return; |
| } |
| printf("%d\r\n",cjson_data->type); |
| |
| cJSON* personA = cJSON_GetObjectItem(cjson_data,"personA");; |
| |
| if(personA) |
| { |
| str = cJSON_Print(cJSON_GetObjectItem(personA,"name")); |
| if(str)printf("name:%s\r\n",str); |
| str = cJSON_Print(cJSON_GetObjectItem(personA,"sex")); |
| if(str)printf("sex:%s\r\n",str); |
| str = cJSON_Print(cJSON_GetObjectItem(personA,"age")); |
| if(str)printf("age:%s\r\n",str); |
| if(str)free(str); |
| } |
| else |
| { |
| printf("personA phase error\r\n"); |
| } |
| return 0; |
| } |
复制
输出结果:
| 6 |
| name:"james" |
| sex:"boy" |
| age:20 |
复制
3.2、解析JSON数组
- cJSON_GetArraySize函数可以获取键值对中的数组,并返回数组个数,我们可以通过遍历数组查找数组中的对应元素内容;
| int MyTest4() |
| { |
| char *str; |
| char *json_str; |
| cJSON *cjson_data; |
| json_str = "{\"list\":[{ \"name\":\"Tom\", \"age\":18, \"sex\":\"boy\" }, { \"name\":\"Jack\", \"age\":19, \"sex\":\"girl\"}]}"; |
| int arr_size; |
| printf("%s\r\n",json_str); |
| cjson_data = cJSON_Parse(json_str); |
| |
| if(!cjson_data) |
| { |
| printf("json phase error\r\n"); |
| return -1; |
| } |
| printf("%d\r\n",cjson_data->type); |
| |
| cJSON *pArray = cJSON_GetObjectItem(cjson_data, "list"); |
| if (NULL == pArray) |
| { |
| printf("not find stu_info\n"); |
| goto err; |
| } |
| int i; |
| int iArraySize = cJSON_GetArraySize(pArray); |
| for (i = 0; i < iArraySize; i++) |
| { |
| printf("******** Stu[%d] info ********\n", i + 1); |
| |
| cJSON *item = cJSON_GetArrayItem(pArray, i); |
| |
| cJSON *pName = cJSON_GetObjectItem(item, "name"); |
| printf("name [%s]\n", pName->valuestring); |
| |
| cJSON *pAge = cJSON_GetObjectItem(item, "age"); |
| printf("age [%d]\n", pAge->valueint); |
| |
| cJSON *pSex = cJSON_GetObjectItem(item, "sex"); |
| printf("sex [%s]\n", pSex->valuestring); |
| } |
| err: |
| cJSON_Delete(cjson_data); |
| return 0; |
| } |
复制
输出结果:
| {"list":[{ "name":"Tom", "age":18, "sex":"boy" }, { "name":"Jack", "age":19, "sex":"girl"}]} |
| 6 |
| ******** Stu[1] info ******** |
| name [Tom] |
| age [18] |
| sex [boy] |
| ******** Stu[2] info ******** |
| name [Jack] |
| age [19] |
| sex [girl] |
| |
复制
3.3、创建JSON数据
| void create_obj_test1() |
| { |
| cJSON *root; |
| cJSON *fmt; |
| cJSON *img; |
| cJSON *thm; |
| int ids[4]={116,943,234,38793}; |
| char *out; |
| |
| root=cJSON_CreateObject(); |
| cJSON_AddItemToObject(root, "Image", img=cJSON_CreateObject()); |
| cJSON_AddNumberToObject(img,"Width",800); |
| cJSON_AddNumberToObject(img,"Height",600); |
| cJSON_AddStringToObject(img,"Title","View from 15th Floor"); |
| cJSON_AddItemToObject(img, "Thumbnail", thm=cJSON_CreateObject()); |
| cJSON_AddStringToObject(thm, "Url", "http:/*www.example.com/image/481989943"); |
| cJSON_AddNumberToObject(thm,"Height",125); |
| cJSON_AddStringToObject(thm,"Width","100"); |
| cJSON_AddItemToObject(img,"IDs", cJSON_CreateIntArray(ids,4)); |
| |
| out=cJSON_Print(root); cJSON_Delete(root); printf("%s\n",out); free(out); |
| } |
复制
输出结果:
| { |
| "Image": { |
| "Width": 800, |
| "Height": 600, |
| "Title": "View from 15th Floor", |
| "Thumbnail": { |
| "Url": "http:/*www.example.com/image/481989943", |
| "Height": 125, |
| "Width": "100" |
| }, |
| "IDs": [116, 943, 234, 38793] |
| } |
| } |
| |
复制