cJSON轻松上手:如何修改JSON对象中的参数值**
在C语言中处理JSON数据,cJSON库无疑是一个非常流行且轻量级的选择,它提供了简洁的API,使得解析、创建和修改JSON变得相对容易,本文将重点介绍如何使用cJSON库来修改JSON对象中已有的参数值。
为什么需要修改JSON参数?
在实际应用中,我们经常需要从外部获取JSON数据(如API响应、配置文件等),然后根据程序逻辑修改其中的某些字段值,最后再将更新后的JSON数据输出或发送出去,更新用户信息、修改设备配置参数、调整算法阈值等。
cJSON修改参数的基本步骤
修改JSON对象中的参数,通常遵循以下基本步骤:
- 解析JSON字符串:需要将包含原始JSON数据的字符串解析成一个cJSON对象。
- 定位目标参数:在解析得到的cJSON对象中,找到你想要修改的那个参数(字段)。
- 修改参数值:使用cJSON提供的API,为目标参数设置新的值。
- (可选)重新生成JSON字符串:如果需要将修改后的JSON对象以字符串形式输出,则可以将cJSON对象转换回JSON字符串。
- 释放内存:无论是原始的JSON字符串还是新生成的JSON字符串,以及cJSON对象本身,都需要在使用完毕后释放内存,避免内存泄漏。
详细操作与示例代码
假设我们有以下JSON字符串,并希望将"age"的值从30修改为31,将"city"的值从"Beijing"修改为"Shanghai":
{
"name": "张三",
"age": 30,
"city": "Beijing",
"isStudent": false
}
包含必要的头文件并初始化
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "cJSON.h" // 确保cJSON.h头文件在包含路径中
解析JSON字符串
const char *json_string = "{\n \"name\": \"张三\",\n \"age\": 30,\n \"city\": \"Beijing\",\n \"isStudent\": false\n}";
cJSON *root = cJSON_Parse(json_string);
if (root == NULL) {
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL) {
fprintf(stderr, "Error before: %s\n", error_ptr);
}
return 1; // 解析失败
}
定位目标参数并修改值
cJSON提供了多种函数来获取和修改不同类型的值。
修改整型值 (age)
cJSON *age_item = cJSON_GetObjectItem(root, "age");
if (age_item && cJSON_IsNumber(age_item)) {
age_item->valueint = 31; // 修改整数值
age_item->valuedouble = 31.0; // 同时修改双精度值,确保一致性
printf("修改 age 为: %d\n", age_item->valueint);
} else {
printf("未找到 age 字段或字段类型不是数字\n");
}
修改字符串值 (city)
cJSON *city_item = cJSON_GetObjectItem(root, "city");
if (city_item && cJSON_IsString(city_item)) {
// 先删除旧的字符串值(如果存在)
cJSON_DeleteItemFromObject(root, "city"); // 或者直接替换指针
// 添加新的字符串值
cJSON_AddStringToObject(root, "city", "Shanghai");
// 或者,如果city_item已经存在且是字符串,可以直接替换其valuestring
// 注意:直接替换指针需要确保旧字符串被正确释放,cJSON_AddStringToObject会处理
// city_item->valuestring = strdup("Shanghai"); // 不推荐直接这样,可能导致内存问题
printf("修改 city 为: %s\n", cJSON_GetObjectItem(root, "city")->valuestring);
} else {
printf("未找到 city 字段或字段类型不是字符串\n");
}
修改布尔值 (isStudent)
假设我们要将"isStudent"从false改为true:
cJSON *is_student_item = cJSON_GetObjectItem(root, "isStudent");
if (is_student_item && cJSON_IsBool(is_student_item)) {
is_student_item->valueint = 1; // cJSON true 用 1 表示
printf("修改 isStudent 为: %s\n", cJSON_IsTrue(is_student_item) ? "true" : "false");
} else {
printf("未找到 isStudent 字段或字段类型不是布尔值\n");
}
添加新参数
如果需要添加一个不存在的参数:
cJSON_AddNumberToObject(root, "score", 95.5); cJSON_AddStringToObject(root, "country", "中国");
删除参数
如果需要删除某个参数:
cJSON_DeleteItemFromObject(root, "name"); // 删除 "name" 字段
重新生成JSON字符串
修改完成后,可以将cJSON对象转换回格式化的JSON字符串:
char *modified_json_string = cJSON_Print(root);
if (modified_json_string != NULL) {
printf("\n修改后的JSON字符串:\n%s\n", modified_json_string);
free(modified_json_string); // 记得释放字符串内存
}
释放内存
释放cJSON对象占用的内存:
cJSON_Delete(root);
完整示例代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"
int main() {
const char *json_string = "{\n \"name\": \"张三\",\n \"age\": 30,\n \"city\": \"Beijing\",\n \"isStudent\": false\n}";
// 1. 解析JSON字符串
cJSON *root = cJSON_Parse(json_string);
if (root == NULL) {
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL) {
fprintf(stderr, "Error before: %s\n", error_ptr);
}
return 1;
}
// 2. 定位并修改 age
cJSON *age_item = cJSON_GetObjectItem(root, "age");
if (age_item && cJSON_IsNumber(age_item)) {
age_item->valueint = 31;
age_item->valuedouble = 31.0;
printf("修改 age 为: %d\n", age_item->valueint);
}
// 3. 定位并修改 city
cJSON *city_item = cJSON_GetObjectItem(root, "city");
if (city_item && cJSON_IsString(city_item)) {
cJSON_DeleteItemFromObject(root, "city"); // 删除旧的
cJSON_AddStringToObject(root, "city", "Shanghai"); // 添加新的
printf("修改 city 为: %s\n", cJSON_GetObjectItem(root, "city")->valuestring);
}
// 4. 定位并修改 isStudent
cJSON *is_student_item = cJSON_GetObjectItem(root, "isStudent");
if (is_student_item && cJSON_IsBool(is_student_item)) {
is_student_item->valueint = 1; // 设为 true
printf("修改 isStudent 为: %s\n", cJSON_IsTrue(is_student_item) ? "true" : "false");
}
// 5. 添加新参数
cJSON_AddNumberToObject(root, "score", 95.5);
// 6. 删除参数
cJSON_DeleteItemFromObject(root, "name");
// 7. 生成修改后的JSON字符串
char *modified_json_string = cJSON_Print(root);
if (modified_json_string != NULL) {
printf("\n修改后的JSON字符串:\n%s\n", modified_json_string);
free(modified_json_string);
}
// 8. 释放cJSON对象
cJSON_Delete(root);
return 0;
}
注意事项
- 内存管理:这是使用cJSON时最重要的注意事项,所有通过cJSON_Parse、cJSON_Print等函数分配的内存,都需要通过cJSON_Delete或相应的free函数释放,避免内存泄漏和悬垂指针。
- 类型检查:在修改JSON项的值之前,最好使用cJSON_IsNumber、cJSON_IsString、cJSON_IsBool等宏检查项的类型,以确保操作的安全性。
- 项的存在性:使用cJSON_GetObjectItem获取项时,返回值可能为NULL(如果项不存在),因此需要检查返回值是否为NULL。
- 直接修改指针:虽然可以直接修改cJSON结构体中的指针(如
valuestring),但这通常不推荐,因为容易导致内存管理混乱,应优先使用cJSON提供的API函数(如cJSON_AddStringToObject)来修改值,这些函数会正确处理内存的分配和释放。 5



还没有评论,来说两句吧...