使用cJSON解析UTF-8格式JSON文件失败的问题求助
问题分析与解决方案
你的代码无法解析JSON的核心原因大概率是UTF-8 BOM干扰(Windows下保存的UTF-8文件常带BOM头),或是缺少错误定位逻辑导致无法排查问题。以下是分步排查和修复方案:
第一步:添加错误定位,精准找到解析失败点
cJSON提供了cJSON_GetErrorPtr()函数,可返回解析失败的位置,帮你快速定位问题。修改解析失败的分支:
if (json == NULL) { const char *error_ptr = cJSON_GetErrorPtr(); if (error_ptr != NULL) { fprintf(stderr, "JSON解析失败,错误位置附近内容:%s\n", error_ptr); } fprintf(stderr, "JSON data couldn't separated.\n"); free(json_data); return 1; }
第二步:处理UTF-8 BOM头
如果你的JSON文件是Windows环境下保存的UTF-8格式,开头会带有3字节的BOM(EF BB BF),而cJSON默认不识别BOM,会把它当成无效的JSON开头导致解析失败。在读取文件后添加BOM检查和跳过逻辑:
fclose(file); json_data[file_size] = '\0'; // 检查并跳过UTF-8 BOM头 if (file_size >= 3 && (unsigned char)json_data[0] == 0xEF && (unsigned char)json_data[1] == 0xBB && (unsigned char)json_data[2] == 0xBF) { // 将数据向前移动3字节,覆盖BOM memmove(json_data, json_data + 3, file_size - 3); // 重新设置字符串结束符 json_data[file_size - 3] = '\0'; }
第三步:修正cJSON的引用方式
直接包含cJSON.c会导致重复定义问题,应该只包含头文件,编译时链接cJSON源文件:
#include <stdio.h> #include <stdlib.h> #include <string.h> // 新增,用于memmove函数 #include "cJSON.h" // 移除#include "cJSON.c"
编译命令改为:
gcc your_code.c cJSON.c -o json_to_csv
第四步:添加CSV写入逻辑(完成作业要求)
在解析成功后,添加写入CSV的代码,示例如下:
// 打开CSV文件 FILE *csv_file = fopen("output.csv", "w, ccs=UTF-8"); if (!csv_file) { fprintf(stderr, "CSV文件无法打开\n"); cJSON_Delete(json); free(json_data); return 1; } // 写入CSV表头 fprintf(csv_file, "ID,Name,Course,Midterm,Final\n"); // 遍历JSON数组并写入数据 if (cJSON_IsArray(json)) { int array_size = cJSON_GetArraySize(json); for (int i = 0; i < array_size; i++) { cJSON *item = cJSON_GetArrayItem(json, i); cJSON *id = cJSON_GetObjectItem(item, "id"); cJSON *name = cJSON_GetObjectItem(item, "name"); cJSON *grades = cJSON_GetObjectItem(item, "grades"); cJSON *course = cJSON_GetObjectItem(item, "course"); cJSON *midterm = cJSON_GetObjectItem(grades, "midterm"); cJSON *final = cJSON_GetObjectItem(grades, "final"); // 写入一行CSV数据(若Name含逗号,需用双引号包裹) fprintf(csv_file, "%d,%s,%s,%d,%d\n", id->valueint, name->valuestring, course->valuestring, midterm->valueint, final->valueint); // 原有打印逻辑可保留用于调试 printf("ID: %d\n", id->valueint); printf("Name: %s\n", name->valuestring); printf("Course: %s\n", course->valuestring); printf("Midterm Grade: %d\n", midterm->valueint); printf("Final Grade: %d\n", final->valueint); } } fclose(csv_file);
额外注意事项
- 确保
data.json和编译后的可执行文件在同一目录,或使用绝对路径打开文件。 - 如果修改后仍解析失败,通过第一步的错误定位信息进一步排查JSON格式是否存在语法问题。
内容的提问来源于stack exchange,提问作者muratkavak
相关产品推荐
相关产品推荐

