You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 23:30:56