足球直播
足球直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
足球直播
足球直播
搜狗输入法
搜狗输入法
快连
快连
快连
快连下载
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
搜狗输入法
搜狗输入法
quickq下载
quickq官网
在C语言中处理JSON数据:实用指南
JSON(JavaScript Object Notation)作为一种轻量级的数据交换格式,因其易读性和跨语言兼容性,已成为现代软件开发中数据存储与传输的主流选择,C语言作为一门接近底层的语言,本身并不内置JSON解析库,开发者需要借助第三方库来处理JSON数据,本文将详细介绍如何在C语言中使用JSON数据,包括常用库的选择、数据解析、构建、读写及错误处理等核心环节。
选择合适的JSON库
在C语言生态中,有多种成熟的JSON库可供选择,以下是几款主流库的特点及适用场景:
cJSON
- 特点:轻量级、单文件实现(仅需
cJSON.h和cJSON.c)、API简单易用,适合嵌入式系统或对资源要求较高的场景。 - 支持功能:JSON解析、构建、遍历、修改及序列化/反序列化。
- GitHub地址:https://github.com/DaveGamble/cJSON
Jansson
- 特点:功能丰富、类型安全、支持UTF-8,提供更完善的错误处理机制,适合复杂JSON场景。
- 依赖:需C99标准支持,部分平台依赖
pkg-config。 - GitHub地址:https://github.com/akheron/jansson
YAJL(Yet Another JSON Library)
- 特点:流式解析(适合大文件)、低内存占用,常用于需要逐块解析JSON的场景(如网络数据流)。
- GitHub地址:https://github.com/lloyd/yajl
ujson
- 特点:高性能,基于SIMD指令优化,适合需要快速解析/生成JSON的高性能场景。
- 限制:API相对复杂,依赖较新的编译器特性。
推荐选择:对于初学者或中小型项目,cJSON是最优选择;若需更健壮的错误处理或流式解析,可考虑Jansson或YAJL,本文以cJSON为例展开讲解。
使用cJSON解析JSON数据
安装与集成
cJSON采用单文件设计,只需下载cJSON.h和cJSON.c,将其添加到项目中即可,若使用CMake,可通过add_subdirectory(cJSON)集成;若使用Makefile,直接编译时包含cJSON.c:
gcc -o demo demo.c cJSON.c -lm
解析JSON字符串
假设有以下JSON字符串,需解析其中的字段:
{
"name": "Alice",
"age": 25,
"isStudent": true,
"courses": ["Math", "Physics"],
"address": {
"city": "Beijing",
"zip": 100000
}
}
示例代码:解析JSON
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
int main() {
const char *json_str = "{"
"\"name\": \"Alice\","
"\"age\": 25,"
"\"isStudent\": true,"
"\"courses\": [\"Math\", \"Physics\"],"
"\"address\": {"
" \"city\": \"Beijing\","
" \"zip\": 100000"
"}"
"}";
// 1. 解析JSON字符串
cJSON *root = cJSON_Parse(json_str);
if (!root) {
printf("Error parsing JSON: %s\n", cJSON_GetErrorPtr());
return 1;
}
// 2. 获取字符串字段(name)
cJSON *name = cJSON_GetObjectItem(root, "name");
if (cJSON_IsString(name)) {
printf("Name: %s\n", name->valuestring);
}
// 3. 获取数字字段(age)
cJSON *age = cJSON_GetObjectItem(root, "age");
if (cJSON_IsNumber(age)) {
printf("Age: %d\n", age->valueint);
}
// 4. 获取布尔字段(isStudent)
cJSON *is_student = cJSON_GetObjectItem(root, "isStudent");
if (cJSON_IsBool(is_student)) {
printf("Is Student: %s\n", cJSON_IsTrue(is_student) ? "true" : "false");
}
// 5. 获取数组字段(courses)
cJSON *courses = cJSON_GetObjectItem(root, "courses");
if (cJSON_IsArray(courses)) {
printf("Courses: ");
cJSON *course = NULL;
cJSON_ArrayForEach(course, courses) {
if (cJSON_IsString(course)) {
printf("%s ", course->valuestring);
}
}
printf("\n");
}
// 6. 获取嵌套对象(address)
cJSON *address = cJSON_GetObjectItem(root, "address");
if (cJSON_IsObject(address)) {
cJSON *city = cJSON_GetObjectItem(address, "city");
cJSON *zip = cJSON_GetObjectItem(address, "zip");
if (cJSON_IsString(city) && cJSON_IsNumber(zip)) {
printf("Address: %s, %d\n", city->valuestring, zip->valueint);
}
}
// 7. 释放JSON对象(避免内存泄漏)
cJSON_Delete(root);
return 0;
}
关键步骤说明:
cJSON_Parse():将JSON字符串解析为cJSON对象树,失败时返回NULL,可通过cJSON_GetErrorPtr()获取错误信息。cJSON_GetObjectItem():从对象中按key获取cJSON节点,若key不存在则返回NULL。- 类型判断:需通过
cJSON_IsString()、cJSON_IsNumber()等宏确认节点类型,避免直接访问valuestring/valueint导致未定义行为。 cJSON_ArrayForEach():遍历数组节点的便捷宏。cJSON_Delete():释放整个cJSON对象树及其所有子节点,必须调用,否则会导致内存泄漏。
构建JSON数据
除了解析,cJSON还支持动态构建JSON对象,以下示例演示如何构建与上述示例相同的JSON数据:
示例代码:构建JSON
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
int main() {
// 1. 创建根对象(JSON对象)
cJSON *root = cJSON_CreateObject();
if (!root) {
printf("Failed to create root object\n");
return 1;
}
// 2. 添加字符串字段(name)
cJSON_AddStringToObject(root, "name", "Alice");
// 3. 添加数字字段(age)
cJSON_AddNumberToObject(root, "age", 25);
// 4. 添加布尔字段(isStudent)
cJSON_AddBoolToObject(root, "isStudent, cJSON_True);
// 5. 添加数组字段(courses)
cJSON *courses = cJSON_CreateArray();
cJSON_AddItemToArray(courses, cJSON_CreateString("Math"));
cJSON_AddItemToArray(courses, cJSON_CreateString("Physics"));
cJSON_AddItemToObject(root, "courses", courses);
// 6. 添加嵌套对象(address)
cJSON *address = cJSON_CreateObject();
cJSON_AddStringToObject(address, "city", "Beijing");
cJSON_AddNumberToObject(address, "zip", 100000);
cJSON_AddItemToObject(root, "address", address);
// 7. 生成JSON字符串(格式化/非格式化)
char *json_str = cJSON_Print(root); // 非格式化(无缩进)
// char *json_str = cJSON_PrintPretty(root); // 格式化(带缩进)
printf("Generated JSON:\n%s\n", json_str);
// 8. 释放内存
free(json_str); // cJSON_Print返回的字符串需手动释放
cJSON_Delete(root);
return 0;
}
关键API说明:
cJSON_CreateObject()/cJSON_CreateArray():创建JSON对象/数组节点。cJSON_AddStringToObject()/cJSON_AddNumberToObject():向对象中添加键值对。cJSON_AddItemToArray():向数组中添加子节点(需先创建子节点)。cJSON_Print()/cJSON_PrintPretty():将cJSON对象序列化为JSON字符串,前者返回紧凑格式,后者返回带缩进的易读格式,返回的字符串需用free()释放。
读写JSON文件
实际开发中,JSON数据常存储在文件中,以下是读写JSON文件的示例:
从文件读取JSON
#include <stdio.h> #include <stdlib.h> #include "cJSON.h" cJSON *load_json_from



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