在C语言中如何获取JSON数据的值
在C语言中处理JSON数据是许多开发场景(如网络请求解析、配置文件读取等)的常见需求,由于C语言本身没有内置JSON支持,我们需要借助第三方库来解析JSON并提取其中的值,本文将以cJSON这一轻量级、广泛使用的开源库为例,详细介绍在C语言中获取JSON值的完整流程,包括环境搭建、基本解析方法和常见场景处理。
为什么选择cJSON库?
cJSON是一个用C语言编制的JSON解析器,具有以下优势:
- 轻量级:核心代码仅包含单个.c和.h文件,无需额外依赖。
- 高效:解析速度快,内存占用低,适合嵌入式或资源受限环境。
- 易用:提供简洁的API,支持JSON的构建、解析、修改和遍历。
- 功能全:支持JSON对象、数组、字符串、数字、布尔值、null等所有标准JSON类型。
环境搭建:获取并集成cJSON
获取cJSON源码
cJSON的官方仓库为https://github.com/DaveGamble/cJSON,你可以通过以下方式获取:
- 克隆仓库:
git clone https://github.com/DaveGamble/cJSON.git - 直接下载:从仓库的“Releases”页面下载最新版本的zip压缩包,解压后包含
cJSON.h(头文件)和cJSON.c(源文件)。
集成到C项目
将cJSON.h和cJSON.c添加到你的C项目中,以GCC编译器为例,编译时需包含源文件:
gcc your_program.c cJSON.c -o your_program -lm
(-lm是链接数学库,cJSON中可能涉及浮点数运算)
解析JSON并获取值的完整流程
假设我们有以下JSON字符串(示例):
{
"name": "Alice",
"age": 25,
"isStudent": false,
"courses": ["Math", "Physics"],
"address": {
"city": "Beijing",
"zip": 100000
},
"phone": null
}
我们的目标是从中提取name、age、courses等字段的值。
解析JSON字符串为cJSON对象
使用cJSON_Parse()函数将JSON字符串解析为cJSON对象(根节点):
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
int main() {
const char *json_string = "{"
"\"name\": \"Alice\","
"\"age\": 25,"
"\"isStudent\": false,"
"\"courses\": [\"Math\", \"Physics\"],"
"\"address\": {\"city\": \"Beijing\", \"zip\": 100000},"
"\"phone\": null"
"}";
// 解析JSON字符串,返回cJSON对象指针
cJSON *root = cJSON_Parse(json_string);
if (root == NULL) {
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL) {
fprintf(stderr, "Error before: %s\n", error_ptr);
}
return 1;
}
// 后续操作...
// 解析完成后,释放内存
cJSON_Delete(root);
return 0;
}
注意:cJSON_Parse()会为JSON对象分配内存,使用完毕后必须调用cJSON_Delete()释放,否则会导致内存泄漏。
获取JSON对象的值(键值对)
对于JSON对象(如示例中的root),通过cJSON_GetObjectItem()函数根据键名获取对应的cJSON项:
// 获取字符串类型的"name"
cJSON *name_item = cJSON_GetObjectItem(root, "name");
if (name_item != NULL && cJSON_IsString(name_item)) {
printf("Name: %s\n", name_item->valuestring);
}
// 获取数字类型的"age"
cJSON *age_item = cJSON_GetObjectItem(root, "age");
if (age_item != NULL && cJSON_IsNumber(age_item)) {
printf("Age: %d\n", age_item->valueint); // 整数用valueint
// printf("Age: %.2f\n", age_item->valuedouble); // 浮点数用valuedouble
}
// 获取布尔类型的"isStudent"
cJSON *is_student_item = cJSON_GetObjectItem(root, "isStudent");
if (is_student_item != NULL && cJSON_IsBool(is_student_item)) {
printf("Is Student: %s\n", cJSON_IsTrue(is_student_item) ? "true" : "false");
}
// 获取null类型的"phone"
cJSON *phone_item = cJSON_GetObjectItem(root, "phone");
if (phone_item != NULL && cJSON_IsNull(phone_item)) {
printf("Phone: null\n");
}
关键点:
- 每个cJSON项都有
type字段,表示其数据类型(如cJSON_String、cJSON_Number等)。 - 通过
cJSON_IsXxx()系列函数(如cJSON_IsString()、cJSON_IsNumber())检查类型,避免直接访问未定义的字段(如对数字类型访问valuestring会导致未行为)。 - 数字类型的值可通过
valueint(整数)或valuedouble(浮点数)获取,根据实际需求选择。
获取JSON数组的值
JSON数组(如示例中的courses)需要先通过cJSON_GetObjectItem()获取数组项,再遍历数组元素:
// 获取"courses"数组
cJSON *courses_item = cJSON_GetObjectItem(root, "courses");
if (courses_item != NULL && cJSON_IsArray(courses_item)) {
int array_size = cJSON_GetArraySize(courses_item);
printf("Courses (%d): ", array_size);
// 遍历数组
cJSON *course = NULL;
cJSON_ArrayForEach(course, courses_item) {
if (cJSON_IsString(course)) {
printf("%s ", course->valuestring);
}
}
printf("\n");
}
说明:
cJSON_GetArraySize()获取数组长度。cJSON_ArrayForEach()是cJSON提供的宏,用于遍历数组元素(相当于for (i = 0; i < size; i++)的简化)。
获取嵌套JSON对象的值
对于嵌套的JSON对象(如示例中的address),需逐层解析:
// 获取"address"嵌套对象
cJSON *address_item = cJSON_GetObjectItem(root, "address");
if (address_item != NULL && cJSON_IsObject(address_item)) {
// 获取嵌套对象中的"city"
cJSON *city_item = cJSON_GetObjectItem(address_item, "city");
if (city_item != NULL && cJSON_IsString(city_item)) {
printf("City: %s\n", city_item->valuestring);
}
// 获取嵌套对象中的"zip"
cJSON *zip_item = cJSON_GetObjectItem(address_item, "zip");
if (zip_item != NULL && cJSON_IsNumber(zip_item)) {
printf("Zip: %d\n", zip_item->valueint);
}
}
完整代码示例
将上述步骤整合,完整的代码如下:
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
int main() {
const char *json_string = "{"
"\"name\": \"Alice\","
"\"age\": 25,"
"\"isStudent\": false,"
"\"courses\": [\"Math\", \"Physics\"],"
"\"address\": {\"city\": \"Beijing\", \"zip\": 100000},"
"\"phone\": null"
"}";
// 1. 解析JSON字符串
cJSON *root = cJSON_Parse(json_string);
if (root == NULL) {
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL) {
fprintf(stderr, "JSON解析错误: %s\n", error_ptr);
}
return 1;
}
// 2. 获取基本类型值
cJSON *name_item = cJSON_GetObjectItem(root, "name");
if (name_item != NULL && cJSON_IsString(name_item)) {
printf("姓名: %s\n", name_item->valuestring);
}
cJSON *age_item = cJSON_GetObjectItem(root, "age");
if (age_item != NULL && cJSON_IsNumber(age_item)) {
printf("年龄: %d\n", age_item->valueint);
}
cJSON *is_student_item = cJSON_GetObjectItem(root, "isStudent");
if (is_student_item != NULL && cJSON_IsBool(is_student_item)) {
printf("是否为学生: %s\n", cJSON_IsTrue(is_student_item) ? "是" : "否");


还没有评论,来说两句吧...