C语言如何接收并处理传入的JSON数据
在跨语言数据交互中,JSON(JavaScript Object Notation)因其轻量、易读的特性,已成为前后端通信、API数据交换的主流格式,C语言作为一门底层编程语言,本身没有内置JSON解析器,需要借助第三方库来实现JSON数据的接收与解析,本文将详细介绍在C语言中如何接收传入的JSON数据,包括数据获取、解析、错误处理及完整代码示例。
接收JSON数据:从输入源到原始字符串
在C语言中,处理JSON数据的第一步是获取原始的JSON字符串,根据数据来源不同,接收方式可分为以下几种:
从文件读取JSON数据
如果JSON数据存储在文件中(如data.json),可以使用标准文件操作函数读取内容,示例代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* read_json_file(const char* filename) {
FILE* file = fopen(filename, "r");
if (!file) {
perror("Failed to open file");
return NULL;
}
// 获取文件大小
fseek(file, 0, SEEK_END);
long file_size = ftell(file);
fseek(file, 0, SEEK_SET);
// 分配内存并读取文件内容
char* json_str = (char*)malloc(file_size + 1);
if (!json_str) {
perror("Memory allocation failed");
fclose(file);
return NULL;
}
size_t bytes_read = fread(json_str, 1, file_size, file);
json_str[bytes_read] = '\0'; // 确保字符串以null结尾
fclose(file);
return json_str;
}
int main() {
char* json_data = read_json_file("data.json");
if (json_data) {
printf("JSON data:\n%s\n", json_data);
free(json_data); // 释放内存
}
return 0;
}
从网络接收JSON数据
在客户端/服务器架构中,JSON数据通常通过HTTP、WebSocket等协议传输,以HTTP为例,可以使用libcurl库接收数据,示例代码如下:
#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
// 回调函数:将接收的数据写入动态增长的缓冲区
static size_t write_callback(void* contents, size_t size, size_t nmemb, void* userp) {
size_t realsize = size * nmemb;
char** buffer_ptr = (char**)userp;
// 重新分配内存(初始为NULL时分配,后续扩容)
char* new_buffer = realloc(*buffer_ptr, realsize + 1);
if (!new_buffer) {
return 0; // 内存分配失败
}
*buffer_ptr = new_buffer;
memcpy(*buffer_ptr, contents, realsize);
(*buffer_ptr)[realsize] = '\0';
return realsize;
}
char* fetch_json_from_url(const char* url) {
CURL* curl = curl_easy_init();
if (!curl) {
fprintf(stderr, "Failed to initialize curl\n");
return NULL;
}
char* json_buffer = NULL;
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &json_buffer);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); // 设置超时时间(秒)
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
curl_easy_cleanup(curl);
return NULL;
}
long response_code;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
if (response_code != 200) {
fprintf(stderr, "HTTP request failed with code: %ld\n", response_code);
curl_easy_cleanup(curl);
return NULL;
}
curl_easy_cleanup(curl);
return json_buffer;
}
int main() {
char* json_data = fetch_json_from_url("https://api.example.com/data");
if (json_data) {
printf("Received JSON data:\n%s\n", json_data);
free(json_data); // 释放内存
}
return 0;
}
从标准输入读取JSON数据
对于命令行交互或管道传输,可通过标准输入(stdin)读取JSON数据,示例代码如下:
#include <stdio.h>
#include <stdlib.h>
char* read_json_from_stdin() {
size_t capacity = 128;
size_t len = 0;
char* buffer = malloc(capacity);
if (!buffer) {
perror("Memory allocation failed");
return NULL;
}
int c;
while ((c = getchar()) != EOF) {
if (len + 1 >= capacity) { // 缓冲区不足时扩容
capacity *= 2;
char* new_buffer = realloc(buffer, capacity);
if (!new_buffer) {
perror("Memory reallocation failed");
free(buffer);
return NULL;
}
buffer = new_buffer;
}
buffer[len++] = (char)c;
}
buffer[len] = '\0';
return buffer;
}
int main() {
printf("Enter JSON data (Ctrl+D to end):\n");
char* json_data = read_json_from_stdin();
if (json_data) {
printf("You entered:\n%s\n", json_data);
free(json_data);
}
return 0;
}
解析JSON数据:选择合适的第三方库
获取JSON字符串后,需使用第三方库将其解析为C语言可操作的数据结构(如结构体、链表等),以下是常用的JSON库及其使用方法:
轻量级库:cJSON
cJSON是一个开源、轻量级的JSON解析库,代码量小(约2000行)、API简单,适合嵌入式或资源受限环境,支持JSON的解析、生成、修改和删除操作。
安装
- 从GitHub下载源码:
https://github.com/DaveGamble/cJSON - 编译为静态库:
gcc -c cJSON.c -o cJSON.o && ar rcs libcJSON.a cJSON.o
示例:解析JSON字符串
假设JSON数据为:
{
"name": "Alice",
"age": 30,
"is_student": false,
"courses": ["Math", "Physics"]
}
解析代码如下:
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
void parse_json_example(const char* json_str) {
cJSON* root = cJSON_Parse(json_str);
if (!root) {
printf("Error parsing JSON: %s\n", cJSON_GetErrorPtr());
return;
}
// 解析字符串字段
cJSON* name = cJSON_GetObjectItem(root, "name");
if (cJSON_IsString(name)) {
printf("Name: %s\n", name->valuestring);
}
// 解析数字字段
cJSON* age = cJSON_GetObjectItem(root, "age");
if (cJSON_IsNumber(age)) {
printf("Age: %d\n", age->valueint);
}
// 解析布尔字段
cJSON* is_student = cJSON_GetObjectItem(root, "is_student");
if (cJSON_IsBool(is_student)) {
printf("Is student: %s\n", cJSON_IsTrue(is_student) ? "true" : "false");
}
// 解析数组字段
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");
}
cJSON_Delete(root); // 释放JSON树内存
}
int main() {
const char* json_data = "{"
"\"name\": \"Alice\","
"\"age\": 30,"
"\"is_student\": false,"
"\"courses\": [\"Math\", \"Physics\"]"
"}";
parse_json_example(json_data);
return 0;
}
功能强大的库:Jansson
Jansson是另一个流行的C语言JSON库,支持严格的JSON规范、错误处理和Unicode,API设计更现代化,适合需要复杂操作的场景。
安装
- 使用包管理器安装(如Ubuntu/Debian):
sudo apt-get install libjansson-dev - 或从源码编译:
https://github.com/akheron/jansson
示例:解析JSON字符串
#include <stdio.h>
#include <jansson.h>
void parse_json_with_jansson(const char* json_str) {
json_error_t error;
json_t* root = json_loads(json_str, 0, &error);
if (!root) {
printf("JSON parse error: %s (line %d, column %d)\n


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