JSON格式,C语言自己实现,以及直接调用库函数(一)
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。以下为你提供不同场景下常见的 JSON 格式示例。
1. 简单对象
JSON 对象是由键值对组成,用花括号 {} 包裹,键和值之间用冒号 : 分隔,多个键值对之间用逗号 , 分隔。
{"name": "John Doe","age": 30,"isStudent": false,"hometown": null
}
2. 嵌套对象
JSON 对象可以嵌套,即一个对象的键对应的值可以是另一个对象。
json
{"person": {"name": "Alice","age": 25,"contact": {"email": "alice@example.com","phone": "123-456-7890"}}
}

3. 数组
JSON 数组是由值组成的有序列表,用方括号 [] 包裹,值之间用逗号 , 分隔。数组中的值可以是不同的数据类型,也可以是对象或数组。
["apple","banana","cherry"
]
4. 对象数组
数组中的元素可以是 JSON 对象。
[{"id": 1,"name": "Product A","price": 19.99},{"id": 2,"name": "Product B","price": 29.99}
]

5. 复杂嵌套结构
结合对象和数组可以形成更复杂的嵌套结构。
{"employees": [{"name": "Bob","department": "Sales","projects": [{"projectName": "Project X","startDate": "2023-01-01"},{"projectName": "Project Y","startDate": "2023-06-01"}]},{"name": "Eve","department": "Marketing","projects": [{"projectName": "Project Z","startDate": "2023-03-01"}]}]
}

6. 包含不同数据类型的对象
{"title": "Sample Document","author": {"firstName": "Jane","lastName": "Smith"},"tags": ["document", "sample"],"views": 1234,"isPublished": true
}

二、
如果没有现成的 JSON 库,要自己实现 JSON 数据的解析和生成,可以按照 JSON 数据的结构特点,通过字符串处理来完成。以下分别介绍如何手动实现 JSON 对象和数组的解析与生成。
1. JSON 解析
解析思路
JSON 对象:JSON 对象由键值对组成,键和值之间用冒号 : 分隔,键值对之间用逗号 , 分隔,整体用花括号 {} 包裹。解析时需要识别键和值,处理嵌套对象和数组。
JSON 数组:JSON 数组由值组成,值之间用逗号 , 分隔,整体用方括号 [] 包裹。解析时需要逐个提取数组元素。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 跳过空白字符
void skip_whitespace(const char **json) {while (**json == ' ' || **json == '\t' || **json == '\n' || **json == '\r') {(*json)++;}
}// 解析字符串
char *parse_string(const char **json) {(*json)++; // 跳过起始的双引号const char *start = *json;while (**json != '\0' && **json != '"') {(*json)++;}size_t len = *json - start;char *str = (char *)malloc(len + 1);if (str == NULL) {return NULL;}memcpy(str, start, len);str[len] = '\0';(*json)++; // 跳过结束的双引号return str;
}// 解析数字
int parse_number(const char **json) {int num = 0;while (**json >= '0' && **json <= '9') {num = num * 10 + (**json - '0');(*json)++;}return num;
}// 解析 JSON 对象
void parse_object(const char **json) {(*json)++; // 跳过起始的花括号skip_whitespace(json);while (**json != '}') {char *key = parse_string(json);skip_whitespace(json);(*json)++; // 跳过冒号skip_whitespace(json);if (**json == '"') {char *value = parse_string(json);printf("Key: %s, Value: %s\n", key, value);free(value);} else if (**json >= '0' && **json <= '9') {int value = parse_number(json);printf("Key: %s, Value: %d\n", key, value);}free(key);skip_whitespace(json);if (**json == ',') {(*json)++;skip_whitespace(json);}}(*json)++; // 跳过结束的花括号
}// 解析 JSON 数组
void parse_array(const char **json) {(*json)++; // 跳过起始的方括号skip_whitespace(json);while (**json != ']') {if (**json == '"') {char *value = parse_string(json);printf("Array value: %s\n", value);free(value);} else if (**json >= '0' && **json <= '9') {int value = parse_number(json);printf("Array value: %d\n", value);}skip_whitespace(json);if (**json == ',') {(*json)++;skip_whitespace(json);}}(*json)++; // 跳过结束的方括号
}// 主解析函数
void parse_json(const char *json) {skip_whitespace(&json);if (*json == '{') {parse_object(&json);} else if (*json == '[') {parse_array(&json);}
}int main() {const char *json_str = "{\"name\": \"John\", \"age\": 30}";parse_json(json_str);return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 生成 JSON 字符串表示的对象
char *generate_json_object(const char *key, const char *value) {size_t key_len = strlen(key);size_t value_len = strlen(value);size_t json_len = 2 + key_len + 2 + 1 + 2 + value_len + 2; // {} "" : ""char *json = (char *)malloc(json_len);if (json == NULL) {return NULL;}sprintf(json, "{\"%s\": \"%s\"}", key, value);return json;
}// 生成 JSON 字符串表示的数组
char *generate_json_array(const char **values, int count) {size_t total_len = 2; // []for (int i = 0; i < count; i++) {total_len += strlen(values[i]) + 2; // ""if (i < count - 1) {total_len++; // ,}}char *json = (char *)malloc(total_len);if (json == NULL) {return NULL;}json[0] = '[';size_t index = 1;for (int i = 0; i < count; i++) {json[index++] = '"';strcpy(json + index, values[i]);index += strlen(values[i]);json[index++] = '"';if (i < count - 1) {json[index++] = ',';}}json[index] = ']';json[index + 1] = '\0';return json;
}int main() {const char *key = "name";const char *value = "John";char *json_obj = generate_json_object(key, value);if (json_obj != NULL) {printf("JSON object: %s\n", json_obj);free(json_obj);}const char *values[] = {"apple", "banana", "cherry"};int count = sizeof(values) / sizeof(values[0]);char *json_arr = generate_json_array(values, count);if (json_arr != NULL) {printf("JSON array: %s\n", json_arr);free(json_arr);}return 0;
}

2


{"employees": [{"name": "Bob","department": "Sales","projects": [{"projectName": "Project X","startDate": "2023-01-01"},{"projectName": "Project Y","startDate": "2023-06-01"}]},{"name": "Eve","department": "Marketing","projects": [{"projectName": "Project Z","startDate": "2023-03-01"}]}]
}
下面是解析该 JSON 数据的 C 语言代码:
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"int main() {const char *json_str = "{\"employees\": [{\"name\": \"Bob\", \"department\": \"Sales\", \"projects\": [{\"projectName\": \"Project X\", \"startDate\": \"2023-01-01\"}, {\"projectName\": \"Project Y\", \"startDate\": \"2023-06-01\"}]}, {\"name\": \"Eve\", \"department\": \"Marketing\", \"projects\": [{\"projectName\": \"Project Z\", \"startDate\": \"2023-03-01\"}]}]}";// 解析 JSON 字符串cJSON *root = cJSON_Parse(json_str);if (root == NULL) {const char *error_ptr = cJSON_GetErrorPtr();if (error_ptr != NULL) {fprintf(stderr, "Error before: %s\n", error_ptr);}return 1;}// 获取 employees 数组cJSON *employees = cJSON_GetObjectItem(root, "employees");if (cJSON_IsArray(employees)) {int array_size = cJSON_GetArraySize(employees);for (int i = 0; i < array_size; i++) {cJSON *employee = cJSON_GetArrayItem(employees, i);cJSON *name = cJSON_GetObjectItem(employee, "name");cJSON *department = cJSON_GetObjectItem(employee, "department");if (cJSON_IsString(name) && cJSON_IsString(department)) {printf("Employee Name: %s\n", name->valuestring);printf("Department: %s\n", department->valuestring);}// 获取 projects 数组cJSON *projects = cJSON_GetObjectItem(employee, "projects");if (cJSON_IsArray(projects)) {int project_size = cJSON_GetArraySize(projects);printf("Projects:\n");for (int j = 0; j < project_size; j++) {cJSON *project = cJSON_GetArrayItem(projects, j);cJSON *projectName = cJSON_GetObjectItem(project, "projectName");cJSON *startDate = cJSON_GetObjectItem(project, "startDate");if (cJSON_IsString(projectName) && cJSON_IsString(startDate)) {printf(" - Project Name: %s\n", projectName->valuestring);printf(" Start Date: %s\n", startDate->valuestring);}}}printf("\n");}}// 释放 cJSON 对象占用的内存cJSON_Delete(root);return 0;
}
- 生成 JSON 数据
下面的代码展示了如何使用 cJSON 库生成一个包含不同数据类型的 JSON 对象:
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"int main() {// 创建根 JSON 对象cJSON *root = cJSON_CreateObject();if (root == NULL) {fprintf(stderr, "Failed to create JSON object\n");return 1;}// 添加字符串类型的键值对cJSON_AddStringToObject(root, "title", "Sample Document");// 创建嵌套的 author 对象cJSON *author = cJSON_CreateObject();if (author == NULL) {fprintf(stderr, "Failed to create author object\n");cJSON_Delete(root);return 1;}cJSON_AddStringToObject(author, "firstName", "Jane");cJSON_AddStringToObject(author, "lastName", "Smith");cJSON_AddItemToObject(root, "author", author);// 创建 tags 数组cJSON *tags = cJSON_CreateArray();if (tags == NULL) {fprintf(stderr, "Failed to create tags array\n");cJSON_Delete(root);return 1;}cJSON_AddItemToArray(tags, cJSON_CreateString("document"));cJSON_AddItemToArray(tags, cJSON_CreateString("sample"));cJSON_AddItemToObject(root, "tags", tags);// 添加数字类型的键值对cJSON_AddNumberToObject(root, "views", 1234);// 添加布尔类型的键值对cJSON_AddBoolToObject(root, "isPublished", 1);// 将 JSON 对象转换为字符串char *json_str = cJSON_Print(root);if (json_str == NULL) {fprintf(stderr, "Failed to print JSON object\n");cJSON_Delete(root);return 1;}// 打印 JSON 字符串printf("%s\n", json_str);// 释放内存free(json_str);cJSON_Delete(root);return 0;
}

下面为你展示如何使用 C 语言结合 cJSON 库,以文件形式读写和保存 JSON 数据。我们会提供两个示例,一个是从文件中读取 JSON 数据并解析,另一个是将生成的 JSON 数据保存到文件中。
1. 从文件读取并解析 JSON 数据
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"// 从文件读取内容到字符串
char* read_file(const char* filename) {FILE* file = fopen(filename, "r");if (file == NULL) {perror("Failed to open file");return NULL;}// 获取文件大小fseek(file, 0, SEEK_END);long size = ftell(file);fseek(file, 0, SEEK_SET);// 分配内存来存储文件内容char* buffer = (char*)malloc(size + 1);if (buffer == NULL) {perror("Failed to allocate memory");fclose(file);return NULL;}// 读取文件内容fread(buffer, 1, size, file);buffer[size] = '\0';fclose(file);return buffer;
}int main() {const char* filename = "input.json";char* json_str = read_file(filename);if (json_str == NULL) {return 1;}// 解析 JSON 字符串cJSON* root = cJSON_Parse(json_str);if (root == NULL) {const char* error_ptr = cJSON_GetErrorPtr();if (error_ptr != NULL) {fprintf(stderr, "Error before: %s\n", error_ptr);}free(json_str);return 1;}// 示例:获取并打印 "name" 字段的值cJSON* name = cJSON_GetObjectItem(root, "name");if (cJSON_IsString(name)) {printf("Name: %s\n", name->valuestring);}// 释放资源free(json_str);cJSON_Delete(root);return 0;
}
2. 生成 JSON 数据并保存到文件
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"int main() {// 创建根 JSON 对象cJSON* root = cJSON_CreateObject();if (root == NULL) {fprintf(stderr, "Failed to create JSON object\n");return 1;}// 添加键值对cJSON_AddStringToObject(root, "name", "John Doe");cJSON_AddNumberToObject(root, "age", 30);// 将 JSON 对象转换为字符串char* json_str = cJSON_Print(root);if (json_str == NULL) {fprintf(stderr, "Failed to print JSON object\n");cJSON_Delete(root);return 1;}// 打开文件以写入模式FILE* file = fopen("output.json", "w");if (file == NULL) {perror("Failed to open file");free(json_str);cJSON_Delete(root);return 1;}// 将 JSON 字符串写入文件fputs(json_str, file);// 关闭文件fclose(file);// 释放内存free(json_str);cJSON_Delete(root);return 0;
}
相关文章:
JSON格式,C语言自己实现,以及直接调用库函数(一)
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。以下为你提供不同场景下常见的 JSON 格式示例。 1. 简单对象 JSON 对象是由键值对组成,用花括号 {} 包裹&…...
MinkowskiEngine安装(CUDA11.8+torch2.0.1+RTX4070TI)
1、背景 1)因为项目要用这个库:MinkowskiEngine,Minkowski Engine — MinkowskiEngine 0.5.3 documentation 然后就用了之前安装好 MinkowskiEngine 的torch1.8.1,cuda11.1的环境。 2)自己的代码出现cuda不支持torch用gpu进行矩…...
Spring监听器Listener
目录 1、Spring监听器简介 2、事件(Event) 3、监听器(Listener) 3、事件发布器 4、监听器使用 4.1、自定义事件 4.2、自定义监听器 4.3、发布事件 4.4、测试 4.5、使用注解方式监听 4.6、异步事件处理 5、总结 1、Spri…...
【深度学习在图像配准中的应用与挑战】
图像配准在深度学习中的解决方案越来越多,尤其是通过卷积神经网络(CNN)和生成对抗网络(GAN)等方法,可以显著提升图像配准的效果,尤其是在处理复杂的非刚性变换和大范围的图像差异时。 1. 基于深…...
使用 Docker-compose 部署 MySQL
使用 Docker Compose 部署 MySQL 本文将详细指导如何使用 docker-compose 部署 MySQL,包括基本配置、启动步骤、数据持久化以及一些高级选项。通过容器化部署 MySQL,你可以快速搭建一个隔离的数据库环境,适用于开发、测试或小型生产场景。 关…...
blender笔记2
一、物体贴地 物体->变换->对齐物体 ->对齐弹窗(对齐模式:反方,相对于:场景原点,对齐:z)。 之后可以设置原点->原点--3d游标 二、面上有阴影 在编辑模式下操作过后,物体面有阴影。 数据-&g…...
特殊符号_符号图案_特殊符号大全
特殊符号↑返回顶部 © ℗ ร ಗ ย ☫ ౖ ஃ ⁜ ☊ ☋ ❡ ๑ ి ▧ ◘ ▩ ▣ ◙ ▨ ۞ ۩ ಔ ృ ☎ ☏ ⍝ ⍦ ▤ ▥ ▦ ✠ @ ಓ ↂ ూ ☮ ி ﺴ ✈ ✉ ✁ ✎ ✐ 〄 # ‡ ☪ ⌚ ☢ ▪ ▫ ✆ ✑ ✒ ☌ ❢ ▬ ☍ □ ■ ؟ ‼ ‽ ☭ ✏ ⌨…...
Unity学习part4
1、ui界面的基础使用 ui可以在2d和矩形工具界面下操作,更方便,画布与游戏窗口的比例一般默认相同 如图所示,图片在画布上显示的位置和在游戏窗口上显示的位置是相同的 渲染模式:屏幕空间--覆盖,指画布覆盖在游戏物体渲…...
【AI绘画】大卫• 霍克尼风格——自然的魔法(一丹一世界)
大卫• 霍克尼,很喜欢这个老头,“艺术是一场战斗”。老先生零九年有了iphone,开始用iphone画画,一零年开始用ipad画画,用指头划拉,据说五分钟就能画一幅,每天早上随手画几幅送给身边的朋友。很c…...
MySQL日志undo log、redo log和binlog详解
MySQL 日志:undo log、redo log、binlog 有什么用? 一、前言 在MySQL数据库中,undo log、redo log和binlog这三种日志扮演着至关重要的角色,它们各自承担着不同的功能,共同保障了数据库的正常运行和数据的完整性。了解…...
C++中的指针
一.指针的定义 在C中,指针是一种特殊的变量,它存储另一个变量的内存地址。简单的说,指针是指向另一个数据类型的“指针”或“引用”,我们可以通过指针来间接操作其他变量的值。 指针的基本语法: 数据类型 *指针变量名 …...
拆解微软CEO纳德拉战略蓝图:AI、量子计算、游戏革命如何改写未来规则!
2025年2月19日 知名博主Dwarkesh Patel对话微软CEO萨蒂亚纳德拉 在最新访谈释放重磅信号:AI将掀起工业革命级增长,量子计算突破引爆材料科学革命,游戏引擎进化为世界模拟器。 整个视频梳理出几大核心观点,揭示科技巨头的未来十年…...
智能算法如何优化数字内容体验的个性化推荐效果
内容概要 在数字内容体验的优化过程中,个性化推荐系统的核心价值在于通过数据驱动的技术手段,将用户需求与内容资源进行高效匹配。系统首先基于用户行为轨迹分析,捕捉包括点击频次、停留时长、交互路径等关键指标,形成对用户兴趣…...
MATLAB在数据分析和绘图中的应用:从基础到实践
引言 股票数据分析是金融领域中的重要研究方向,通过对历史价格、成交量等数据的分析,可以帮助投资者更好地理解市场趋势和做出决策。MATLAB作为一种强大的科学计算工具,提供了丰富的数据处理和可视化功能,非常适合用于股票数据的…...
AI客服-接入deepseek大模型到微信(本地部署deepseek集成微信自动收发消息)
1.本地部署 1.1 ollama Ollama软件通过其高度优化的推理引擎和先进的内存管理机制,显著提升了大型语言模型在本地设备上的运行效率。其核心采用了量化技术(Quantization)以降低模型的计算复杂度和存储需求,同时结合张量并行计算&…...
Host文件没有配置ip解析,导致请求接口速度慢
Linux访问第三方接口速度慢 现象 在测试环境,Linux的服务器中,要访问第三方接口;速度有时快,有时慢。 有时候第一次访问比较慢,第二次访问比较快。第三方人员,排查之后,第三方接口没有问题&am…...
excel导入Mysql中时间格式异常
问题描述: 当使用xls/xlsx/csv导入mysql中,如果列是时间类型比如excel表中显示2024/02/20 09:18:00,导入后时间可能就会变成1900-01-01 09:18:00这样。 问题原因: 这是由于excel表中和数据库中的时间类型不匹配导致。 问题解决…...
vue 判断一个属性值,如果是null或者空字符串或者是空格没有值的情况下,赋值为--
在 Vue 中,可以通过多种方式来判断一个属性值是否为 null、空字符串或者仅包含空格,如果满足这些条件则将其赋值为 --。下面分别介绍在模板和计算属性、方法中实现的具体做法。 1. 在模板中直接判断 如果只需要在模板中对属性值进行显示处理,…...
JavaWeb-Tomcat服务器
文章目录 Web服务器存在的意义关于Web服务器软件Tomcat服务器简介安装Tomcat服务器Tomcat服务器源文件解析配置Tomcat的环境变量启动Tomcat服务器一个最简单的webapp(不涉及Java) Web服务器存在的意义 我们之前介绍过Web服务器进行通信的原理, 但是我们当时忘记了一点, 服务器…...
vue语法---样式操作-行内样式
文章目录 直接写死的行内样式v-bind绑定对象(静态样式)对象数组 直接写死的行内样式 <template><div v-bind:style"{color:red}">睡觉</div> </template><script>export default{data() {return {}},methods:{}, mounted(){},} </…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...
R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
