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

如何用json-c处理多JSON对象:遍历、计数、缓冲区及内存释放问题

使用json-c处理多JSON对象的问题解答

嘿,我来帮你解决这几个json-c使用的问题,咱们一个个来捋清楚:

问题1:遍历多个对象并获取总数

首先要注意,你的JSON文档里是两个独立的JSON对象,不是标准的JSON数组(用[]包裹的结构),所以json_tokener_parse()只会解析第一个对象就停止了。要处理这种非标准的多JSON对象文件,你需要用到json-c的增量解析能力,通过json_tokener分步解析内容:

  • 初始化一个json_tokener对象,用来逐步处理输入数据
  • 循环解析,每成功解析出一个完整对象就计数加一,同时处理该对象的字段
  • 直到文件所有内容都被处理完毕,最终的计数就是对象总数

问题2:避免固定大小Buffer,逐个读取对象

固定buffer的问题确实会在对象数量多或者单个对象过大时触发异常,而增量解析刚好能解决这个问题:不需要一次性读取整个文件,而是每次读取一小段数据(比如128字节,大小可以按需调整),喂给json_tokener,它会自动拼接数据、判断是否能解析出完整对象。这种方式既不会因为buffer过小截断数据,也不会占用过多内存,完全实现逐个读取解析对象的需求。

问题3:内存释放的正确姿势

你当前的free(name); free(password);这类操作是完全错误的!因为json_object_object_get_ex()获取的指针是指向父JSON对象内部的子对象引用,这些对象的内存由json-c的引用计数机制管理,你不能直接用free()释放它们。

正确的内存管理方式:

  • 对于每个完整解析出的JSON对象,处理完毕后调用json_object_put(obj)来减少引用计数,当计数归0时,json-c会自动释放该对象及其所有子对象的内存
  • 不要手动释放子对象指针,否则会触发内存错误或double free
  • 初始化的json_tokener对象,最后要用json_tokener_free()销毁

修改后的完整示例代码

#include <stdio.h>
#include <stdlib.h>
#include <json-c/json.h>

int main(){
    FILE* fichier = NULL;
    char buffer[128]; // 用小buffer即可,增量解析不需要大内存
    struct json_tokener *tok = json_tokener_new();
    struct json_object *obj;
    int object_count = 0;
    enum json_tokener_error err;

    fichier = fopen("../../data/Personne.json", "r");
    if (fichier == NULL) {
        printf("Une ERREUR est survenue lors du chargement des différents comptes\n");
        json_tokener_free(tok);
        return 1;
    }

    // 增量解析循环:逐步读取文件并解析对象
    while (fread(buffer, 1, sizeof(buffer), fichier) > 0) {
        obj = json_tokener_parse_ex(tok, buffer, sizeof(buffer));
        // 循环检查是否解析出完整对象(buffer中可能包含多个对象)
        while ((err = json_tokener_get_error(tok)) == json_tokener_success) {
            object_count++;
            printf("=== 对象 %d ===\n", object_count);
            
            struct json_object *name, *password, *salt, *email;
            json_object_object_get_ex(obj, "name", &name);
            json_object_object_get_ex(obj, "password", &password);
            json_object_object_get_ex(obj, "salt", &salt);
            json_object_object_get_ex(obj, "email", &email);

            printf("name : %s\n", json_object_get_string(name));
            printf("password : %s\n", json_object_get_string(password));
            printf("salt : %s\n", json_object_get_string(salt));
            printf("email : %s\n", json_object_get_string(email));

            // 释放当前解析出的对象
            json_object_put(obj);
            // 尝试解析buffer中剩余的内容
            obj = json_tokener_parse_ex(tok, "", 0);
        }
        // 如果是"需要更多数据"的错误,继续读取文件;其他错误则终止
        if (err != json_tokener_continue) {
            printf("解析错误: %s\n", json_tokener_error_desc(err));
            break;
        }
    }

    // 处理文件末尾可能剩余的未解析对象
    obj = json_tokener_parse_ex(tok, "", 0);
    if ((err = json_tokener_get_error(tok)) == json_tokener_success) {
        object_count++;
        printf("=== 对象 %d ===\n", object_count);
        struct json_object *name, *password, *salt, *email;
        json_object_object_get_ex(obj, "name", &name);
        json_object_object_get_ex(obj, "password", &password);
        json_object_object_get_ex(obj, "salt", &salt);
        json_object_object_get_ex(obj, "email", &email);

        printf("name : %s\n", json_object_get_string(name));
        printf("password : %s\n", json_object_get_string(password));
        printf("salt : %s\n", json_object_get_string(salt));
        printf("email : %s\n", json_object_get_string(email));
        json_object_put(obj);
    }

    printf("\n总共有 %d 个对象\n", object_count);

    // 清理所有资源
    fclose(fichier);
    json_tokener_free(tok);
    return 0;
}

代码核心说明

  1. 用json_tokener实现增量解析,小buffer循环读取文件,避免内存占用问题
  2. 每解析出一个完整对象就计数、处理字段,然后通过json_object_put()释放对象内存
  3. 处理了文件末尾剩余数据的情况,确保所有对象都被解析
  4. 完全遵循json-c的内存管理规则,没有手动free子对象

内容的提问来源于stack exchange,提问作者magjico

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 10:12:46