介绍
cJSON 库是C语言中的最常用的 JSON 库。github 地址是 https://github.com/DaveGamble/cJSON 。
安装
环境是 Ubuntu 16.04。需要先安装cmake。
cJSON 库安装步骤如下:
git clone https://github.com/DaveGamble/cJSON.git
cd cJSON/
mkdir build
cd build/
cmake ..
make
make install
执行完上述命令后,cJSON.h
头文件会安装在 /usr/local/include/cjson
目录下。libcjson.so
库文件会安装在 /usr/local/lib
目录下。还需要将/usr/local/lib
目录添加到 /etc/ld.so.conf
文件中,然后执行 /sbin/ldconfig
,否则程序在运行时会报 error while loading shared libraries: libcjson.so.1: cannot open shared object file: No such file or directory 错误。
使用
还是使用显示器支持的分辨率的例子来说明如何使用 cJSON 库生成和解析JSON如下的格式:
{
"name": "Awesome 4K",
"resolutions": [
{
"width": 1280,
"height": 720
},
{
"width": 1920,
"height": 1080
},
{
"width": 3840,
"height": 2160
}
]
}
使用 cJSON 库时,程序只需包含<cjson/cJSON.h>
头文件。而在编译时,需要添加 -lcjson
选项。
生成JSON格式
生成 JSON 对象有两种方式:
- 一是调用 cJSON_CreateXXX 创建相应类型的值(sJSON结构),然后调用 cJSON_AddItemToObject 将值加入到对象中。
- 二是直接调用 cJSON_AddXXXToObject 创建并添加值到对象中 。
生成 JSON 数组只有一种方式,就是先调用 cJSON_CreateXXX 创建相应类型的值,然后调用 cJSON_AddItemToArray 将值加入到数组中。
最后都要调用 cJSON_Print 将对象或数组转化成 JSON 格式的字符串,调用 cJSON_Delete 释放对象。
生成 JSON 对象的第一种示例代码如下:
//NOTE: Returns a heap allocated string, you are required to free it after use.
char* create_monitor(void)
{
const unsigned int resolution_numbers[3][2] = {
{1280, 720},
{1920, 1080},
{3840, 2160}
};
char *string = NULL;
cJSON *name = NULL;
cJSON *resolutions = NULL;
cJSON *resolution = NULL;
cJSON *width = NULL;
cJSON *height = NULL;
size_t index = 0;
/* 创建一个对象 */
cJSON *monitor = cJSON_CreateObject();
if (monitor == NULL)
{
goto end;
}
/* 创建一个字符串 */
name = cJSON_CreateString("Awesome 4K");
if (name == NULL)
{
goto end;
}
/* 将字符串添加到对象中 */
/* after creation was successful, immediately add it to the monitor,
* thereby transfering ownership of the pointer to it */
cJSON_AddItemToObject(monitor, "name", name);
/* 创建一个数组 */
resolutions = cJSON_CreateArray();
if (resolutions == NULL)
{
goto end;
}
/* 将数组添加到对象中 */
cJSON_AddItemToObject(monitor, "resolutions", resolutions);
for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index)
{
resolution = cJSON_CreateObject();
if (resolution == NULL)
{
goto end;
}
/* 将对象添加到数组中 */
cJSON_AddItemToArray(resolutions, resolution);
/* 创建一个数字 */
width = cJSON_CreateNumber(resolution_numbers[index][0]);
if (width == NULL)
{
goto end;
}
/* 将数字添加到对象中 */
cJSON_AddItemToObject(resolution, "width", width);
height = cJSON_CreateNumber(resolution_numbers[index][1]);
if (height == NULL)
{
goto end;
}
cJSON_AddItemToObject(resolution, "height", height);
}
/* 转换成 JSON 格式的字符串 */
string = cJSON_Print(monitor);
if (string == NULL)
{
fprintf(stderr, "Failed to print monitor.\n");
}
end:
/* 释放对象 */
cJSON_Delete(monitor);
return string;
}
生成 JSON 对象的第二种示例代码如下:
//NOTE: Returns a heap allocated string, you are required to free it after use.
char *create_monitor_with_helpers(void)
{
const unsigned int resolution_numbers[3][2] = {
{1280, 720},
{1920, 1080},
{3840, 2160}
};
char *string = NULL;
cJSON *resolutions = NULL;
size_t index = 0;
cJSON *monitor = cJSON_CreateObject();
/* 将字符串添加到对象中 */
if (cJSON_AddStringToObject(monitor, "name", "Awesome 4K") == NULL)
{
goto end;
}
/* 将数组添加到对象中,返回一个数组 */
resolutions = cJSON_AddArrayToObject(monitor, "resolutions");
if (resolutions == NULL)
{
goto end;
}
for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index)
{
cJSON *resolution = cJSON_CreateObject();
/* 将数字添加到对象中 */
if (cJSON_AddNumberToObject(resolution, "width", resolution_numbers[index][0]) == NULL)
{
goto end;
}
if(cJSON_AddNumberToObject(resolution, "height", resolution_numbers[index][1]) == NULL)
{
goto end;
}
cJSON_AddItemToArray(resolutions, resolution);
}
string = cJSON_Print(monitor);
if (string == NULL) {
fprintf(stderr, "Failed to print monitor.\n");
}
end:
cJSON_Delete(monitor);
return string;
}
解析JSON格式
解析 JSON 格式,首先要调用 cJSON_Parse 生成用于解析的 cJSON 结构,然后调用 cJSON_GetObjectItemCaseSensitive或 cJSON_GetObjectItem 获取对应名字的值,用 cJSON_IsXXX 判断值的类型是否正确,然后用 结构中的 valuestring 或 valuedouble 等成员获取值。实例函数代码如下,这个函数判断显示器是否支持 1920x1080 分辨率:
/* return 1 if the monitor supports full hd, 0 otherwise */
int supports_full_hd(const char *const monitor)
{
const cJSON *resolution = NULL;
const cJSON *resolutions = NULL;
const cJSON *name = NULL;
int status = 0;
/* 创建一个用于解析的 cJSON 结构 */
cJSON *monitor_json = cJSON_Parse(monitor);
if (monitor_json == NULL)
{
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL)
{
fprintf(stderr, "Error before: %s\n", error_ptr);
}
status = 0;
goto end;
}
/* 获取名为“name”的值 */
name = cJSON_GetObjectItemCaseSensitive(monitor_json, "name");
if (cJSON_IsString(name) && (name->valuestring != NULL))
{
printf("Checking monitor \"%s\".\n", name->valuestring);
}
/* 获取名为“resolutions“的值,它是一个数组 */
resolutions = cJSON_GetObjectItemCaseSensitive(monitor_json, "resolutions");
/* 遍历数组 */
cJSON_ArrayForEach(resolution, resolutions)
{
cJSON *width = cJSON_GetObjectItemCaseSensitive(resolution, "width");
cJSON *height = cJSON_GetObjectItemCaseSensitive(resolution, "height");
if (!cJSON_IsNumber(width) || !cJSON_IsNumber(height))
{
status = 0;
goto end;
}
if ((width->valuedouble == 1920) && (height->valuedouble == 1080))
{
status = 1;
goto end;
}
}
end:
cJSON_Delete(monitor_json);
return status;
}
main 函数
代码如下:
int main(int argc, char **argv)
{
char *monitor = create_monitor_with_helpers();
printf("%s\n", monitor);
if (supports_full_hd(monitor)) {
printf("It support full HD.\n");
}
free(monitor);
}
程序运行结果如下:
{
"name": "Awesome 4K",
"resolutions": [{
"width": 1280,
"height": 720
}, {
"width": 1920,
"height": 1080
}, {
"width": 3840,
"height": 2160
}]
}
Checking monitor "Awesome 4K".
It support full HD.