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

C语言libcurl自定义回调返回JSON含多余数字致解析失败问题

问题根源

你遇到的末尾额外数字,是因为libcurl传给回调的data是原始二进制字节流,没有自动添加C字符串必需的终止符\0。直接用printf("%s", data)或json_tokener_parse(data)时,函数会越界读取内存里的随机内容,那些0、1就是这么来的——而libcurl默认回调内部处理了字符串终止逻辑,所以不会出问题。

解决办法

1. 打印数据用fwrite替代printf("%s")

不需要依赖字符串终止符,直接按实际响应长度打印:

static size_t callback(void *data, size_t size, size_t nmemb, void *userp)
{
    size_t real_size = size * nmemb;
    printf("This is the data:\n");
    fwrite(data, 1, real_size, stdout);
    printf("\n");

    // 解析JSON前先给数据加终止符
    char *json_str = malloc(real_size + 1);
    if(json_str) {
        memcpy(json_str, data, real_size);
        json_str[real_size] = '\0';
        jobj = json_tokener_parse(json_str);
        free(json_str);
    }

    return real_size;
}

2. 严谨方案:先收集全部响应再处理

libcurl的回调可能被多次调用(大响应会分片返回),单次回调直接解析JSON也可能出错。可以用userp传递缓冲区,收集完所有数据后统一解析:

// 定义结构体存储响应数据
typedef struct {
    char *buffer;
    size_t size;
} ResponseData;

static size_t callback(void *data, size_t size, size_t nmemb, void *userp)
{
    ResponseData *resp = (ResponseData *)userp;
    size_t real_size = size * nmemb;

    // 扩容缓冲区
    char *new_buf = realloc(resp->buffer, resp->size + real_size + 1);
    if(!new_buf) return 0; // 内存分配失败直接返回

    resp->buffer = new_buf;
    memcpy(resp->buffer + resp->size, data, real_size);
    resp->size += real_size;
    resp->buffer[resp->size] = '\0'; // 确保字符串终止

    return real_size;
}

// 使用示例
int main() {
    ResponseData resp = {NULL, 0};
    CURL *curl = curl_easy_init();
    if(curl) {
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback);
        // 设置其他请求参数...
        curl_easy_perform(curl);

        // 请求完成后处理数据
        if(resp.buffer) {
            printf("完整响应:\n%s\n", resp.buffer);
            jobj = json_tokener_parse(resp.buffer);
            free(resp.buffer);
        }
        curl_easy_cleanup(curl);
    }
}

3. 临时应急:手动复制数据并加终止符(仅适用于小响应)

如果能确定响应体积很小、只会触发一次回调,可以临时复制数据并添加终止符,但不推荐用于大响应场景:

static size_t callback(void *data, size_t size, size_t nmemb, void *userp)
{
    size_t real_size = size * nmemb;
    char temp[1024]; // 假设响应不超过1023字节
    if(real_size < 1023) {
        memcpy(temp, data, real_size);
        temp[real_size] = '\0';
        printf("This is the data:\n%s\n", temp);
        jobj = json_tokener_parse(temp);
    }
    return real_size;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 05:31:20