C语言处理JSON字符串:接收与解析指南**
在C语言中直接处理JSON(JavaScript Object Notation)字符串,相较于一些现代高级语言(如Python、JavaScript)而言,会显得稍微繁琐一些,因为C语言本身没有内置对JSON格式的原生支持,JSON是一种轻量级的数据交换格式,易于人阅读和编写,也易于机器解析和生成,在C语言项目中,我们通常需要借助第三方库来简化JSON字符串的接收和解析工作,本文将重点介绍如何在C语言中接收JSON字符串,并使用常用的第三方库进行解析。
接收JSON字符串
接收JSON字符串的方式取决于你的应用程序是如何获取数据的,常见的场景包括:
- 从文件读取:JSON数据存储在文件中,程序需要读取文件内容。
- 从网络接收:通过HTTP请求、WebSocket等方式从服务器或其他客户端获取JSON数据。
- 从用户输入获取:通过命令行参数、标准输入(键盘)等方式接收用户提供的JSON字符串。
示例1:从文件读取JSON字符串
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_JSON_STRING_LENGTH 10240 // 假设JSON字符串最大长度
int main() {
FILE *file = fopen("data.json", "r"); // 打开JSON文件
if (file == NULL) {
perror("Error opening file");
return 1;
}
char json_string[MAX_JSON_STRING_LENGTH];
if (fgets(json_string, sizeof(json_string), file) != NULL) {
// fgets会读取换行符,如果不需要可以去掉
size_t len = strlen(json_string);
if (len > 0 && json_string[len - 1] == '\n') {
json_string[len - 1] = '\0';
}
printf("Received JSON string from file:\n%s\n", json_string);
// 这里可以继续解析json_string
} else {
printf("Failed to read JSON string from file.\n");
}
fclose(file);
return 0;
}
示例2:从标准输入(命令行)接收JSON字符串
#include <stdio.h>
#include <stdlib.h>
#define MAX_JSON_STRING_LENGTH 10240
int main() {
char json_string[MAX_JSON_STRING_LENGTH];
printf("Please enter a JSON string: ");
if (fgets(json_string, sizeof(json_string), stdin) != NULL) {
// 去掉可能的换行符
size_t len = strlen(json_string);
if (len > 0 && json_string[len - 1] == '\n') {
json_string[len - 1] = '\0';
}
printf("Received JSON string from stdin:\n%s\n", json_string);
// 这里可以继续解析json_string
} else {
printf("Failed to read JSON string from stdin.\n");
}
return 0;
}
示例3:从网络接收(简化的概念示例,实际需用网络库如libcurl、socket等)
// 这是一个高度简化的概念,实际网络编程更复杂
// char* receive_json_from_network() {
// // 1. 建立网络连接
// // 2. 接收数据
// // 3. 将接收到的数据拼接成完整的JSON字符串
// // 4. 返回JSON字符串
// }
解析JSON字符串
接收到JSON字符串后,我们需要将其解析成C语言中的数据结构(如结构体、数组、字符串、数字等)以便程序使用,C语言中流行的JSON解析库有:
- cJSON:一个轻量级、易用的C语言JSON解析器,本文将主要介绍cJSON。
- Jansson:另一个功能丰富、性能较好的C语言JSON库。
- json-c:一个老牌的C语言JSON库。
这里我们以cJSON为例进行详细说明。
安装cJSON库
如果你使用Linux系统,可以通过包管理器安装,
sudo apt-get install libcjson-dev # 对于Debian/Ubuntu
或者从源码编译安装:从cJSON的GitHub仓库下载源码,然后按照README中的说明进行编译和安装。
使用cJSON解析JSON字符串
假设我们有以下JSON字符串:
{
"name": "John Doe",
"age": 30,
"isStudent": false,
"courses": ["Math", "Science", "History"],
"address": {
"street": "123 Main St",
"city": "New York"
}
}
解析步骤如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cjson/cJSON.h" // 包含cJSON头文件
void print_json(cJSON *item, int depth);
int main() {
const char *json_string = "{"
"\"name\": \"John Doe\","
"\"age\": 30,"
"\"isStudent\": false,"
"\"courses\": [\"Math\", \"Science\", \"History\"],"
"\"address\": {"
" \"street\": \"123 Main St\","
" \"city\": \"New York\""
"}"
"}";
// 1. 解析JSON字符串
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;
}
// 2. 获取数据
// 获取name (字符串)
cJSON *name_item = cJSON_GetObjectItemCaseSensitive(root, "name");
if (cJSON_IsString(name_item) && (name_item->valuestring != NULL)) {
printf("Name: %s\n", name_item->valuestring);
}
// 获取age (数字)
cJSON *age_item = cJSON_GetObjectItemCaseSensitive(root, "age");
if (cJSON_IsNumber(age_item)) {
printf("Age: %d\n", age_item->valueint);
}
// 获取isStudent (布尔值)
cJSON *is_student_item = cJSON_GetObjectItemCaseSensitive(root, "isStudent");
if (cJSON_IsBool(is_student_item)) {
printf("Is Student: %s\n", cJSON_IsTrue(is_student_item) ? "true" : "false");
}
// 获取courses (数组)
cJSON *courses_item = cJSON_GetObjectItemCaseSensitive(root, "courses");
if (cJSON_IsArray(courses_item)) {
printf("Courses: ");
cJSON *course = NULL;
cJSON_ArrayForEach(course, courses_item) {
if (cJSON_IsString(course)) {
printf("%s ", course->valuestring);
}
}
printf("\n");
}
// 获取address (对象)
cJSON *address_item = cJSON_GetObjectItemCaseSensitive(root, "address");
if (cJSON_IsObject(address_item)) {
cJSON *street_item = cJSON_GetObjectItemCaseSensitive(address_item, "street");
cJSON *city_item = cJSON_GetObjectItemCaseSensitive(address_item, "city");
if (cJSON_IsString(street_item) && street_item->valuestring != NULL &&
cJSON_IsString(city_item) && city_item->valuestring != NULL) {
printf("Address: %s, %s\n", street_item->valuestring, city_item->valuestring);
}
}
// 3. 释放内存
cJSON_Delete(root);
return 0;
}
代码解释:
- 包含头文件:
#include "cjson/cJSON.h"。 - 解析JSON字符串:
cJSON_Parse()函数将JSON字符串解析成一个cJSON对象指针,如果解析失败,它会返回NULL,我们可以通过cJSON_GetErrorPtr()获取错误信息。 - 获取数据项:使用
cJSON_GetObjectItemCaseSensitive()根据键名获取JSON对象中的项,注意这个函数是区分大小写的,还有cJSON_GetObjectItem()不区分大小写。 - 检查数据类型:cJSON提供了
cJSON_IsString(),cJSON_IsNumber(),cJSON_IsBool(),cJSON_IsArray(),cJSON_IsObject()等宏来判断数据项的类型。 - 访问值:
- 字符串:
item->valuestring - 整数:
item->valueint(对于浮点数,可以使用item->valuedouble) - 布尔值:
cJSON_IsTrue(item)或cJSON_IsFalse(item) - 数组:使用
cJSON_ArrayForEach宏遍历数组元素。 - 对象:再次使用
cJSON_GetObjectItem获取嵌套对象的项。
- 字符串:
- **释放内存



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