cjson指南
cjson指南
cjson
是一款轻量级 C
解析 JSON
的程序库。
cJSON
本文都是根据官方文件 https://github.com/DaveGamble/cJSON 翻译并只保留基本介绍和接口说明,版本适用于 V1.7.15
。
1 说明
1.1 网址
1.2 json
JSON 全称 JavaScript Object Notation
,即 JS对象简谱,是一种轻量级的数据格式。它采用完全独立于编程语言的文本格式来存储和表示数据,语法简洁、层次结构清晰,易于人阅读和编写,同时也易于机器解析和生成,有效的提升了网络传输效率。
JSON对象是一个无序的”名称/值”键值对的集合:
- 以”{“开始,以”}”结束,允许嵌套使用;
- 每个名称和值成对出现,名称和值之间使用”:”分隔;
- 键值对之间用”,”分隔
- 在这些字符前后允许存在无意义的空白符;
对于键值,可以有如下值:
- 一个新的json对象
- 数组:使用”[“和”]”表示
- 数字:直接表示,可以是整数,也可以是浮点数
- 字符串:使用引号”表示
- 字面值:false、null、true中的一个(必须是小写)
1
2
3
4
5
6
7
8
9
{
"name": "Tom",
"age": 18,
"location": {
"county": "China",
"address": "四川"
},
"skill": ["C++", "Java", "Python"]
}
2 详细介绍
2.1 下载或克隆
1
git clone https://github.com/DaveGamble/cJSON.git
2.2 数据结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
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 valueint;
/* The item's number, if type==cJSON_Number */
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;
next
:指向下一个键值对;prev
:指向上一个键值对;child
:指向子节点键值对;type
:用于表示该键值对中值的类型;valuestring
:如果键值类型(type)是字符串,则将该指针指向键值;valueint
:如果键值类型(type)是整数,则将该指针指向键值;valuedouble
:如果键值类型(type)是浮点数,则将该指针指向键值;string
:用于表示该键值对的名称;
2.3 接口
接口 | 作用 |
---|---|
cJSON_Parse(const char *value) | 解析字符串为json格式 |
cJSON_ParseWithLength(const char *value, size_t buffer_length) | 解析字符串为json格式(指定长度) |
cJSON_GetErrorPtr(void) | 获取解析失败信息 |
cJSON_Print(const cJSON *item) | 返回格式化json字符串 |
cJSON_PrintUnformatted(const cJSON *item) | 返回未格式化json字符串 |
cJSON_GetArraySize(const cJSON *array) | 获取json数组大小 |
cJSON_GetArrayItem(const cJSON *array, int index) | 获取对应数组下标 |
cJSON_GetObjectItem(const cJSON * const object, const char * const string) | 根据名称获取json键值 |
cJSON_Is{}(const cJSON * const item) | 判断该项类型,详情查看 cJSON Type |
cJSON_Create{}() | 创建对应cjson对象,包括单独键值对,数组 |
cJSON_AddItemToArray(cJSON *array, cJSON *item) | 添加数组 |
cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) | 添加对象 |
cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) | 数组中插入新数据 |
cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); | 数组中替换(更新) |
cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem) | 对象替换 |
cJSON_Add{}ToObject() | 添加数据到对应层级 |
cJSON_malloc(size_t size) | 申请内存 |
cJSON_free(void *object) | 释放申请内存 |
cJSON_Delete(cJSON *item) | 释放 cjson 内存,删除自身和子集 |
3 使用
3.1 核心文件
1
2
cJSON.h
cJSON.c
3.2 简单使用流程
(1)读取文件
1
2
3
4
5
6
7
8
9
10
11
12
13
1. 解析数据
1.1 读取文件 (如果使用字符串可以跳过该步骤)
1.2 解析字符串 cJSON * json = cJSON_Parse(str);
1.3 结果 失败cJSON_GetErrorPtr() 成功printf("%s", cJSON_Print(root))
2. 加载数据
2.1 普通数据,根据 key 获取对应的 value
cJSON * name = cJSON_GetObjectItem(json, "name");
2.2 解析数组,获取到数组
cJSON * link = cJSON_GetArrayItem(links, i);
3. 数据类型
valuestring, valueint, valuedouble
4. 记得销毁指针
cJSON_Delete(root);
(2)写入文件
1
2
3
4
5
6
7
8
9
10
11
12
13
1. 创建对象
cJSON * root = cJSON_CreateObject();
2. 添加普通对象
cJSON * item1 = cJSON_CreateObject();
cJSON_AddStringToObject(item1, "text", "我是一个字符串数据");
cJSON_AddItemToObject(root, "data1", item1);
3. 添加数组对象
cJSON * array = cJSON_CreateArray();
cJSON * obj = cJSON_CreateObject();
cJSON_AddItemToArray(array, obj);
cJSON_AddItemToObject(root, "data3", array);
4. 生成字符串,存入文件
char * str = cJSON_Print(root);
3.3 代码
一定要记得释放内存
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#include <cstring>
#include <iostream>
#include "cJSON.h"
// 字符串解析
void demo1()
{
std::string str = "{\
\"name\": \"张三\",\
\"age\" : 18,\
\"addr\" : {\
\"country\": \"中国\",\
\"address\" : \"四川\"\
},\
\"skills\" : [\"C++\", \"Java\", \"Python\"]\
}";
// 字符串解析成 cJSON 格式
cJSON* json = cJSON_Parse(str.c_str());
// 解析结果
if (!json)
{
std::cout << "Error: " << cJSON_GetErrorPtr() << std::endl;
}
else
{
std::cout << cJSON_Print(json) << std::endl;
// 修改或添加数据
cJSON_ReplaceItemInObject(json, "age", cJSON_CreateNumber(20));
cJSON_InsertItemInArray(cJSON_GetObjectItem(json, "skills"), 1, cJSON_CreateString("Go"));
// 根据 key 获取对应的 value
cJSON* name = cJSON_GetObjectItem(json, "name");
// 判断数据类型
if (name->type == cJSON_String)
{
std::cout << "name = " << name->valuestring << std::endl;
}
cJSON* age = cJSON_GetObjectItem(json, "age");
if (age->type == cJSON_Number)
{
std::cout << "age = " << age->valueint << std::endl;
}
cJSON* addr = cJSON_GetObjectItem(json, "addr");
std::cout << "addr = " << cJSON_GetObjectItem(addr, "country")->valuestring
<< " " << cJSON_GetObjectItem(addr, "address")->valuestring << std::endl;
cJSON* skills = cJSON_GetObjectItem(json, "skills");
int len = cJSON_GetArraySize(skills);
std::cout << "skills= [";
for (size_t i = 0; i < len; i++)
{
cJSON* skill = cJSON_GetArrayItem(skills, i);
std::cout << skill->valuestring << ",";
}
std::cout << "\b]" << std::endl;
}
cJSON_Delete(json);
}
// 文件读取解析
void demo2()
{
FILE* file = fopen("read.json", "r");
if (file == nullptr)
{
std::cout << "Open Fail" << std::endl;
return;
}
// 到文件尾部取文件大小,然后回到文件头部
fseek(file, 0, SEEK_END);
int file_size = ftell(file);
fseek(file, 0, SEEK_SET);
char* buffer = (char*)calloc(sizeof(char), file_size);
if (-1 == fread(buffer, sizeof(char), file_size, file))
{
fclose(file);
std::cout << "Read Fail" << std::endl;
return;
}
fclose(file);
cJSON* root = cJSON_Parse(buffer);
free(buffer);
// 解析结果
if (!root)
{
cJSON_Delete(root);
std::cout << "Error: " << cJSON_GetErrorPtr() << std::endl;
}
else
{
// 解析数组
cJSON* links = cJSON_GetObjectItem(root, "links");
int len = cJSON_GetArraySize(links);
for (size_t i = 0; i < len; i++)
{
cJSON* link = cJSON_GetArrayItem(links, i);
std::cout << cJSON_GetObjectItem(link, "name")->valuestring << std::endl;
std::cout << cJSON_GetObjectItem(link, "url")->valuestring << std::endl;
}
}
cJSON_Delete(root);
}
// 创建 json
void demo3()
{
// 1. 创建cJSON对象
cJSON* root = cJSON_CreateObject();
// 2. 创建对象数据1
cJSON* item1 = cJSON_CreateObject();
cJSON_AddStringToObject(item1, "text", "我是一个字符串数据1");
cJSON_AddNumberToObject(item1, "number", 666);
cJSON_AddBoolToObject(item1, "state1", cJSON_False);
cJSON_AddBoolToObject(item1, "state2", cJSON_True);
cJSON_AddNullToObject(item1, "state3");
cJSON_AddItemToObject(root, "data1", item1);
// 2. 创建对象数据2
cJSON* item2 = cJSON_CreateObject();
cJSON_AddStringToObject(item2, "text", "我是一个字符串数据2");
cJSON_AddNumberToObject(item2, "number", 666);
cJSON_AddBoolToObject(item2, "state1", cJSON_False);
cJSON_AddBoolToObject(item2, "state2", cJSON_True);
cJSON_AddNullToObject(item2, "state3");
cJSON_AddItemToObject(root, "data2", item2);
// 2. 创建数组
cJSON* array = cJSON_CreateArray();
cJSON_AddItemToObject(root, "data3", array);
for (size_t i = 0; i < 3; ++i)
{
cJSON* obj = cJSON_CreateObject();
cJSON_AddItemToArray(array, obj);
cJSON* width = cJSON_CreateNumber(i * 10);
cJSON_AddItemToObject(obj, "width", width);
cJSON* height = cJSON_CreateNumber(i * 10);
cJSON_AddItemToObject(obj, "height", height);
}
// 3. 打印生成的结果
char* str = cJSON_Print(root);
std::cout << str << std::endl;
FILE* file = fopen("write.json", "w");
if (file == nullptr)
{
std::cout << "Open Fail" << std::endl;
return;
}
fwrite(str, sizeof(char), strlen(str), file);
fclose(file);
// 4. 释放空间
cJSON_Delete(root);
}
int main()
{
// 字符串解析
demo1();
// 文件读取解析
// demo2();
// 创建 json
// demo3();
return 0;
}
本文由作者按照 CC BY 4.0 进行授权