使用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; }
关键细节说明
- 严格类型校验:
- 先判断数组元素是否为
cJSON_Object类型,跳过非对象元素 - 必须用
cJSON_IsNumber校验valuea、valueb的类型,避免把字符串或其他类型当成数字处理
- 先判断数组元素是否为
- 避免重复添加:
- 每次添加前检查
va1/va2是否已经存在,存在则跳过当前对象
- 每次添加前检查
- 正确遍历数组:
- 使用
cJSON_ArrayForEach宏遍历数组,自动处理每个元素,不会出现指针偏移错误
- 使用
- 按位运算修正:
- 用
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
相关产品推荐
相关产品推荐

