当前位置: 首页 > web >正文

C-JSON接口的使用

一、cJSON 核心数据结构

cJSON 的所有操作都围绕 cJSON 结构体展开,它代表 JSON 中的一个节点(可以是对象、数组、字符串、数字等):

typedef struct cJSON 
{struct cJSON *next, *prev;  // 用于链表(数组/对象的子节点)struct cJSON *child;        // 子节点(对象/数组的元素)int type;                   // 节点类型(见下方宏定义)char *valuestring;          // 字符串值(type为字符串时有效)int valueint;               // 整数值(type为数字时可用)double valuedouble;         // 浮点值(type为数字时有效)char *string;               // 键名(对象的键)
} cJSON;

节点类型宏定义(部分常用):

  • cJSON_False:布尔值 false
  • cJSON_True:布尔值 true
  • cJSON_NULL:null
  • cJSON_Number:数字(整数 / 浮点数)
  • cJSON_String:字符串
  • cJSON_Array:数组
  • cJSON_Object:对象

二、解析 JSON 字符串(核心接口)

1. 解析整个 JSON 字符串
cJSON *cJSON_Parse(const char *value);
  • 功能:将 JSON 字符串解析为 cJSON 结构体(根节点)。
  • 参数:value 为 JSON 格式的字符串。
  • 返回:成功返回根节点指针,失败返回 NULL
2. 获取节点类型
int cJSON_GetType(const cJSON *item);
3. 从对象中获取子节点(按键名)
cJSON *cJSON_GetObjectItem(const cJSON *object, const char *string);
  • 功能:从 JSON 对象中根据键名获取子节点。
  • 参数:object 为对象节点,string 为键名。
  • 返回:找到的子节点指针,未找到返回 NULL
4. 获取数组长度
int cJSON_GetArraySize(const cJSON *array);

功能:获取 JSON 数组的元素个数

5. 从数组中获取元素(按索引)
cJSON *cJSON_GetArrayItem(const cJSON *array, int index);
  • 功能:从数组中根据索引获取元素。
  • 参数:array 为数组节点,index 为索引(从 0 开始)。
6. 释放解析后的 cJSON 结构
void cJSON_Delete(cJSON *c);
  • 功能:释放整个 cJSON 链表(根节点及所有子节点),防止内存泄漏。

三、构建 JSON 字符串(核心接口)

1. 创建基础类型节点
cJSON *cJSON_CreateNumber(double num);       // 创建数字节点
cJSON *cJSON_CreateString(const char *string); // 创建字符串节点
cJSON *cJSON_CreateBool(cJSON_bool boolean);   // 创建布尔节点
cJSON *cJSON_CreateNull(void);                // 创建 null 节点
2. 创建数组和对象
cJSON *cJSON_CreateArray(void);  // 创建空数组
cJSON *cJSON_CreateObject(void); // 创建空对象
3. 向数组添加元素
void cJSON_AddItemToArray(cJSON *array, cJSON *item);
  • 功能:将节点添加到数组末尾。
4. 向对象添加键值对
void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
  • 功能:向对象添加键为 string、值为 item 的键值对。
5. 将 cJSON 结构转为字符串
char *cJSON_Print(const cJSON *item);         // 格式化输出(带缩进)
char *cJSON_PrintUnformatted(const cJSON *item); // 紧凑输出(无缩进)
  • 返回:动态分配的字符串,使用后需用 free() 释放。

四、示例代码:

#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"  // 需包含 cJSON 头文件// 解析 JSON 示例
void parse_json_example(const char *json_str) 
{// 1. 解析 JSON 字符串cJSON *root = cJSON_Parse(json_str);if (root == NULL) {printf("解析 JSON 失败: %s\n", cJSON_GetErrorPtr());return;}// 2. 获取 "success" 字段(字符串)cJSON *success = cJSON_GetObjectItem(root, "success");if (success && success->type == cJSON_String) {printf("请求状态: %s\n", success->valuestring);}// 3. 获取 "result" 对象cJSON *result = cJSON_GetObjectItem(root, "result");if (result && result->type == cJSON_Object) {// 4. 从 result 中获取城市和温度cJSON *city = cJSON_GetObjectItem(result, "city");cJSON *temp = cJSON_GetObjectItem(result, "temp");if (city && city->type == cJSON_String) {printf("城市: %s\n", city->valuestring);}if (temp && temp->type == cJSON_String) {printf("温度: %s℃\n", temp->valuestring);}// 5. 解析 "index" 数组cJSON *index_array = cJSON_GetObjectItem(result, "index");if (index_array && index_array->type == cJSON_Array) {int size = cJSON_GetArraySize(index_array);printf("生活指数(共 %d 条):\n", size);for (int i = 0; i < size; i++) {cJSON *item = cJSON_GetArrayItem(index_array, i);if (item && item->type == cJSON_String) {printf("  - %s\n", item->valuestring);}}}}// 6. 释放资源cJSON_Delete(root);
}// 构建 JSON 示例
void create_json_example() 
{// 1. 创建根对象cJSON *root = cJSON_CreateObject();if (root == NULL) {printf("创建根对象失败\n");return;}// 2. 向根对象添加字段cJSON_AddItemToObject(root, "name", cJSON_CreateString("天气查询"));cJSON_AddItemToObject(root, "version", cJSON_CreateNumber(1.0));cJSON_AddItemToObject(root, "enabled", cJSON_CreateBool(1));  // true// 3. 创建数组并添加元素cJSON *cities = cJSON_CreateArray();cJSON_AddItemToArray(cities, cJSON_CreateString("北京"));cJSON_AddItemToArray(cities, cJSON_CreateString("上海"));cJSON_AddItemToObject(root, "support_cities", cities);// 4. 转为字符串并打印char *json_str = cJSON_Print(root);  // 格式化输出if (json_str) {printf("\n构建的 JSON:\n%s\n", json_str);free(json_str);  // 释放字符串}// 5. 释放资源cJSON_Delete(root);
}int main() 
{// 模拟 API 返回的 JSON 字符串const char *api_response = "{""\"success\":\"1\",""\"result\":{""\"city\":\"北京\",""\"temp\":\"25\",""\"weather\":\"晴\",""\"index\":[\"适宜出行\",\"注意防晒\"]""}""}";// 解析示例parse_json_example(api_response);// 构建示例create_json_example();return 0;
}

http://www.xdnf.cn/news/18828.html

相关文章:

  • “无人驾驶与人”之浅析
  • 技术攻坚与安全兜底——消防智能仓储立库管理系统的国产化硬核实力
  • **FastAPI + Pydantic v2 + JSON‑RPC 2.0**,实现 A2A 规范核心方法
  • 18 继续学习
  • SpringBoot的条件装配原理
  • 量子计算驱动的Python医疗诊断编程前沿展望(下)
  • localhost和127.0.0.1的区别
  • 不再让Windows更新!Edge游戏助手卸载及关闭自动更新
  • 雪花算法数据库主键
  • Shell 学习笔记 - Shell 三剑客篇
  • 【ABAP4】基本语法1
  • CI/CD企业案例详解
  • Linux下usb设备驱动涉及的结构体
  • 记一次生产环境Hbase填坑之路、Hbase客户端登陆、kerberos认证、端口列表、Pod上手撕代码【Hbase最佳实践】
  • 酶 EC number 预测工具CLEAN的安装和使用
  • Java 线程池详解:原理、使用与源码深度解析
  • 从全栈开发到微服务架构:一次真实的Java面试实录
  • 【图像处理基石】如何把非笑脸转为笑脸?
  • Git连接Github远程仓库的代理设置
  • Java:HashSet的使用
  • Linux shell脚本条件循环
  • 基础篇(下):神经网络与反向传播(程序员视角)
  • 【论文阅读 | arXiv 2025 | WaveMamba:面向RGB-红外目标检测的小波驱动Mamba融合方法】
  • Multitouch for mac 触控板手势增强软件
  • Zynq开发实践(Verilog、仿真、FPGA和芯片设计)
  • RAG智能问答为什么需要进行Rerank?
  • 【K8s】整体认识K8s之namespace
  • 低功耗模式DMA数据搬运问题解析
  • 模块测试与低功耗模式全攻略
  • 【Java】springboot的自动配置