JSON
# JSON
Owner: -QVQ-
# JSON
JavaScript Object Notation,一种轻量级的数据格式
JSON对象是一个无序的"名称/值"键值对的集合:
- 以"
{
“开始,以”}
"结束,允许嵌套使用; - 每个名称和值成对出现,名称和值之间使用"
:
"分隔; - 键值对之间用"
,
"分隔 - 在这些字符前后允许存在无意义的空白符;
对于键值,可以有如下值:
- 一个新的json对象
- 数组:使用"
[
“和”]
"表示 - 数字:直接表示,可以是整数,也可以是浮点数
- 字符串:使用引号
"
表示 - 字面值:false、null、true中的一个(必须是小写)
{
"name": "mculover666",
"age": 22,
"weight": 55.5,
"address":
{
"country": "China",
"zip-code": 111111
},
"skill": ["c", "Java", "Python"],
"student": false
}
2
3
4
5
6
7
8
9
10
11
12
# cJSON
C语言编写的JSON数据解析器
git clone [https://github.com/DaveGamble/cJSON.git](https://github.com/DaveGamble/cJSON.git)
其中的源文件只有两个:
cJSON.h
cJSON.c
其使用cJSON结构体来表示一个JSON数据
struct cJSON
/* The cJSON structure: */ typedef struct cJSON { struct cJSON *next;//指向下一个键值对 struct cJSON *prev;//指向上一个键值对 struct cJSON *child;//指向下一个嵌套的键值对,或者一个数组 int type;//表示该键值对的名称 char *valuestring;//如果键值类型(type)是字符串,则将该指针指向键值 int valueint;//如果键值类型(type)是整数,则将该指针指向键值 double valuedouble;//如果键值类型(type)是浮点数,则将该指针指向键值; char *string;//表示该键值对的名称 } cJSON;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 数据创建API
char* cJSON_Print(const cJSON *item);
将链表的内容输出到一个字符串中
cJSON_CreateObject()
创建一个JSON数据对象(链表头结点)
cJSON_AddStringToObject(cJSON*, char*, char*)
添加一条字符串数据,
第一个参数是添加对象
第二个参数是参数名字
第三个参数是添加内容
cJSON_AddNumberToObject(cJSON*, char*, int)
添加一个数值数据,可以是int或者float数据
第一个参数是添加对象
第二个参数是参数名字
第三个参数是添加内容
cJSON_AddItemToObject(cJSON* c1, char*, cJSON* c2)
添加一个cJSON内容,向c1添加c2,第二个参数是名字
cJSON_CreateArray()
创建一个数组对象
cJSON_CreateString(char*)
将char*类型转换为一个cJSON对象
cJSON_AddItemToArray(cJSON *array, cJSON *item)
添加item数组内容入array,直接没有办法插入,必须调用上面的转换函数
cJSON_AddFalseToObject(cJSON *object, const char *string)
添加一个bool数据,false或true
对于上面哪个JSON数据的封装操作
#include <stdio.h> #include "cJSON.h" int main(void) { cJSON* cjson_test = NULL; cJSON* cjson_address = NULL; cJSON* cjson_skill = NULL; char* str = NULL; /* 创建一个JSON数据对象(链表头结点) */ cjson_test = cJSON_CreateObject(); /* 添加一条字符串类型的JSON数据(添加一个链表节点) */ cJSON_AddStringToObject(cjson_test, "name", "mculover666"); /* 添加一条整数类型的JSON数据(添加一个链表节点) */ cJSON_AddNumberToObject(cjson_test, "age", 22); /* 添加一条浮点类型的JSON数据(添加一个链表节点) */ cJSON_AddNumberToObject(cjson_test, "weight", 55.5); /* 添加一个嵌套的JSON数据(添加一个链表节点) */ cjson_address = cJSON_CreateObject(); cJSON_AddStringToObject(cjson_address, "country", "China"); cJSON_AddNumberToObject(cjson_address, "zip-code", 111111); cJSON_AddItemToObject(cjson_test, "address", cjson_address); /* 添加一个数组类型的JSON数据(添加一个链表节点) */ cjson_skill = cJSON_CreateArray(); cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "C" )); cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "Java" )); cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "Python" )); cJSON_AddItemToObject(cjson_test, "skill", cjson_skill); /* 添加一个值为 False 的布尔类型的JSON数据(添加一个链表节点) */ cJSON_AddFalseToObject(cjson_test, "student"); /* 打印JSON对象(整条链表)的所有数据 */ str = cJSON_Print(cjson_test); printf("%s\n", str); return 0; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 数据解析API
cJSON * cJSON_Parse(const char *value);
将一个符合json数据结构的字符串转换为cJSON结构体。,返回链表头节点指针
cJSON * cJSON_GetObjectItem(const cJSON * const object, const char * const string);
根据键值对的名称从链表中取出对应的值,返回该键值对(链表节点)的地址
一个函数可以读取所有类型的
int cJSON_GetArraySize(const cJSON *array);
返回数组类型数据的大小
cJSON * cJSON_GetArrayItem(const cJSON *array, int index);
返回数组类型的cJSON
例子
#include <stdio.h> #include "cJSON.h" char *message = "{ \ \"name\":\"mculover666\", \ \"age\": 22, \ \"weight\": 55.5, \ \"address\": \ { \ \"country\": \"China\",\ \"zip-code\": 111111\ }, \ \"skill\": [\"c\", \"Java\", \"Python\"],\ \"student\": false \ }"; int main(void) { cJSON* cjson_test = NULL; cJSON* cjson_name = NULL; cJSON* cjson_age = NULL; cJSON* cjson_weight = NULL; cJSON* cjson_address = NULL; cJSON* cjson_address_country = NULL; cJSON* cjson_address_zipcode = NULL; cJSON* cjson_skill = NULL; cJSON* cjson_student = NULL; int skill_array_size = 0, i = 0; cJSON* cjson_skill_item = NULL; /* 解析整段JSO数据 */ cjson_test = cJSON_Parse(message); if(cjson_test == NULL) { printf("parse fail.\n"); return -1; } /* 依次根据名称提取JSON数据(键值对) */ cjson_name = cJSON_GetObjectItem(cjson_test, "name"); cjson_age = cJSON_GetObjectItem(cjson_test, "age"); cjson_weight = cJSON_GetObjectItem(cjson_test, "weight"); printf("name: %s\n", cjson_name->valuestring); printf("age:%d\n", cjson_age->valueint); printf("weight:%.1f\n", cjson_weight->valuedouble); /* 解析嵌套json数据 */ cjson_address = cJSON_GetObjectItem(cjson_test, "address"); cjson_address_country = cJSON_GetObjectItem(cjson_address, "country"); cjson_address_zipcode = cJSON_GetObjectItem(cjson_address, "zip-code"); printf("address-country:%s\naddress-zipcode:%d\n", cjson_address_country->valuestring, cjson_address_zipcode->valueint); /* 解析数组 */ cjson_skill = cJSON_GetObjectItem(cjson_test, "skill"); skill_array_size = cJSON_GetArraySize(cjson_skill); printf("skill:["); for(i = 0; i < skill_array_size; i++) { cjson_skill_item = cJSON_GetArrayItem(cjson_skill, i); printf("%s,", cjson_skill_item->valuestring); } printf("\b]\n"); //若要将json的数据写入文件需要先用cJSON_PrintUnformatted转为字符串,再写入 /* 解析布尔型数据 */ cjson_student = cJSON_GetObjectItem(cjson_test, "student"); if(cjson_student->valueint == 0) { printf("student: false\n"); } else { printf("student:error\n"); } return 0; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
在实际使用时,如果提前不确定数据类型,应该先判断type的值,确定数据类型,再从对应的数据域中提取数据
char * cJSON_Print(const cJSON *item);
char* cJSON_PrintUnformatted(cJSON *)
将cJSON数据解析成JSON字符串,并在堆中开辟一块char*的内存空间存储JSON字符串。cJSON_PrintUnformatted()
与cJSON_Print()
类似,只是打印输出不带格式,而只是一个字符串数据
# 内存问题
void cJSON_Delete(cJSON *item);
内存释放函数,如果有嵌套会连带删除
钩子函数
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
typedef struct cJSON_Hooks
{
void *(CJSON_CDECL *malloc_fn)(size_t sz);
void (CJSON_CDECL *free_fn)(void *ptr);
} cJSON_Hooks;
2
3
4
5
CJSON_PUBLIC(void *) cJSON_malloc(size_t size); CJSON_PUBLIC(void) cJSON_free(void *object);
# 数据替换
cJSON_ReplaceItemInObjectCaseSensitive(旧的json,char* key,新的json)
函数的功能是将JSON对象中指定名称的键值对替换为新的键值对。指定的名称字符串是区分大小写的。新的键值对是由一个cJSON指针提供的。函数返回一个指向替换后的对象的指针,如果对象或字符串为NULL,则返回NULL。
# yyjson
高性能json库