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

使用cJSON修改JSON对象数组时重复添加字段的问题

解决C语言中cJSON给JSON数组对象添加字段的问题

问题核心

给JSON数组里满足valueb=58且valuea为数字的对象,一次性添加va1(valuea右移8位)和va2(valuea与255按位与)字段,要求不能重复添加,也不能修改错误的对象。

常见错误原因

你之前的代码大概率踩了这些坑:

  • 遍历数组时没校验元素类型,把非对象元素当成对象处理
  • 没检查目标字段是否已存在,导致重复添加
  • 数组遍历指针操作错误,误用同一个指针修改了错误对象
  • 没正确判断valuea、valueb的类型,比如把字符串类型的数字当成数字处理

正确实现代码

#include <stdio.h>
#include <cJSON.h>

int main() {
    // 原始JSON示例
    const char *raw_json = 
        "[{\"valuea\": 12345, \"valueb\": 58}, "
         "{\"valuea\": \"not_a_number\", \"valueb\": 58}, "
         "{\"valuea\": 67890, \"valueb\": 59}, "
         "{\"valuea\": 11223, \"valueb\": 58}]";

    // 解析JSON
    cJSON *root = cJSON_Parse(raw_json);
    if (root == NULL) {
        printf("JSON解析失败: %s\n", cJSON_GetErrorPtr());
        return 1;
    }

    // 确认根节点是数组
    if (!cJSON_IsArray(root)) {
        printf("根节点不是数组\n");
        cJSON_Delete(root);
        return 1;
    }

    // 遍历数组中的每个元素
    cJSON *item = NULL;
    cJSON_ArrayForEach(item, root) {
        // 先判断当前元素是否是对象
        if (!cJSON_IsObject(item)) {
            continue;
        }

        // 获取valueb字段,判断是否是数字且等于58
        cJSON *valueb = cJSON_GetObjectItemCaseSensitive(item, "valueb");
        if (!cJSON_IsNumber(valueb) || valueb->valueint != 58) {
            continue;
        }

        // 获取valuea字段,判断是否是数字
        cJSON *valuea = cJSON_GetObjectItemCaseSensitive(item, "valuea");
        if (!cJSON_IsNumber(valuea)) {
            continue;
        }

        // 检查是否已经添加过va1/va2,避免重复添加
        if (cJSON_GetObjectItemCaseSensitive(item, "va1") != NULL || 
            cJSON_GetObjectItemCaseSensitive(item, "va2") != NULL) {
            continue;
        }

        // 计算va1和va2的值
        int va1 = valuea->valueint >> 8;
        int va2 = valuea->valueint & 0xFF; // 用0xFF代替256,按位与取低8位更准确

        // 创建新字段并添加到当前对象
        cJSON_AddNumberToObject(item, "va1", va1);
        cJSON_AddNumberToObject(item, "va2", va2);
    }

    // 输出处理后的JSON
    char *processed_json = cJSON_Print(root);
    printf("处理后的JSON:\n%s\n", processed_json);

    // 释放资源
    cJSON_free(processed_json);
    cJSON_Delete(root);

    return 0;
}

关键细节说明

  1. 严格类型校验:
    • 先判断数组元素是否为cJSON_Object类型,跳过非对象元素
    • 必须用cJSON_IsNumber校验valuea、valueb的类型,避免把字符串或其他类型当成数字处理
  2. 避免重复添加:
    • 每次添加前检查va1/va2是否已经存在,存在则跳过当前对象
  3. 正确遍历数组:
    • 使用cJSON_ArrayForEach宏遍历数组,自动处理每个元素,不会出现指针偏移错误
  4. 按位运算修正:
    • 用0xFF(即255)代替256做按位与,因为256的二进制是100000000,和数字按位与结果为0,无法取到低8位

测试结果

原始JSON:

[{"valuea": 12345, "valueb": 58}, {"valuea": "not_a_number", "valueb": 58}, {"valuea": 67890, "valueb": 59}, {"valuea": 11223, "valueb": 58}]

处理后的正确输出:

[
    {
        "valuea": 12345,
        "valueb": 58,
        "va1": 48,
        "va2": 57
    },
    {
        "valuea": "not_a_number",
        "valueb": 58
    },
    {
        "valuea": 67890,
        "valueb": 59
    },
    {
        "valuea": 11223,
        "valueb": 58,
        "va1": 43,
        "va2": 111
    }
]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 16:24:55