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 对象是由键值对组成,用花括号 {} 包裹&…...
学习整理安装php的uuid扩展以及uuid调用方法
学习整理安装php的uuid扩展以及uuid调用方法 1、安装uuid依赖库2、下载并安装3、ini中添加扩展4、re2c版本报错5、uuid调用方法 1、安装uuid依赖库 yum -y install uuid uuid-devel e2fsprogs-devel libuuid-devel2、下载并安装 点我下载uuid安装包 wget http://pecl.php.ne…...
Elasticsearch实战应用:从“搜索小白”到“数据侦探”的进阶之路
引言:Elasticsearch——数据世界的“福尔摩斯” 大家好,今天我们要聊的是一个在数据世界中扮演“福尔摩斯”角色的工具——Elasticsearch。如果你曾经为海量数据的搜索和分析头疼不已,那Elasticsearch就是你的救星!它不仅能帮你快…...
Orange 单体架构 - 快速启动
1 后端服务 1.1 基础设施 组件说明版本MySQLMySQL数据库服务5.7/8JavaJava17redis-stackRedis向量数据库最新版本Node安装Node22.11.0 1.2 orange-dependencies-parent 项目Maven依赖版本管理 1.2.1 项目克隆 GitHub git clone https://github.com/hengzq/orange-depende…...
Spring Boot 入门 与 无法解析符号 springframework 的解决
Spring Boot 入门的关键步骤 1 创建 Maven 工程 操作目的: 通过 Maven 工程来管理项目依赖,Spring Boot 本身就依赖 Maven 或 Gradle 来简化依赖管理。 操作方法: 打开 IDEA(IntelliJ IDEA)。点击 New Project&#…...
3D模型在线转换工具:轻松实现3DM转OBJ
3D模型在线转换是一款功能强大的在线工具,支持多种3D模型格式的在线预览和互转。无论是工业设计、建筑设计,还是数字艺术领域,这款工具都能满足您的需求。 3DM与OBJ格式简介 3DM格式:3DM是一种广泛应用于三维建模的文件格式&…...
java中双亲委派详解
什么是双亲委派机制? 双亲委派机制(Parent Delegation Model)是Java类加载器(ClassLoader)加载类时的一种策略。它的核心思想是:当一个类加载器收到加载类的请求时,不会立即自己加载࿰…...
【Python爬虫(27)】探索数据可视化的魔法世界
【Python爬虫】专栏简介:本专栏是 Python 爬虫领域的集大成之作,共 100 章节。从 Python 基础语法、爬虫入门知识讲起,深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑,覆盖网页、图片、音频等各类数据爬取ÿ…...
网络安全-js安全知识点与XSS常用payloads
简介 JavaScript 是一种轻量级的编程语言,定义了HTML的行为。它与Java的关系类似周杰和周杰伦的关系(即没有关系)。 用法 HTML 中的脚本必须位于 <script> 与 </script> 标签之间。 脚本可被放置在 HTML 页面的 <body>…...
ip属地是电话号码吗怎么改
在数字化时代,IP属地作为网络身份的一部分,对于许多互联网用户来说并不陌生。然而,关于IP属地的具体含义以及如何更改它,却常常让一些用户感到困惑。特别是当提到IP属地与电话号码之间的关系时,更是容易让人产生误解。…...
Ubuntu中使用yum命令出现错误提示:Command ‘yum‘ not found
Ubuntu中使用yum命令出现以下错误提示: 解决方法如下 1、使用su或sudo -s命令使普通用户切换为root用户 2、然后检测是否安装了build-essential程序包,输入命令: apt-get install build-essential 3、进度走完后安装yum,输入命令: apt-get install yum 如果成功安装ÿ…...
【Vue.js 和 React.js 的主要区别是什么?】
Vue.js 和 React.js 的主要区别是什么? 前言 Vue.js 和 React.js 是当前最流行的两个前端框架,它们都用于构建用户界面,但在设计理念、语法和使用方式上有显著差异。本文将从多个维度对比 Vue.js 和 React.js 的主要区别,帮助开…...
HarmonyOS NEXT 全栈开发实战手册(API 12+)
一、HarmonyOS NEXT 架构升级与关键技术 1.1 分布式能力增强(重点标注) 跨设备计算网格:支持动态分配 GPU/CPU/NPU 资源 // 分布式渲染示例(API 12) import renderService from ohos.distributedHardware.render; l…...
【rt-thread】rt-thread 控制 led 的两种方式
1. pin设备 #define LED_PIN 3int led(void) {rt_uint8_t count;rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT); for(count 0 ; count < 10 ;count){ rt_pin_write(LED_PIN, PIN_HIGH);rt_kprintf("led on, count : %d %d\r\n", count, rt_pin_read(LED_PIN));…...
Python爬虫系列教程之第十三篇:构建高可用爬虫系统 —— 混合架构与自动化监控
大家好,欢迎继续关注本系列爬虫教程!随着爬虫项目规模的不断扩大和业务需求的提升,单一技术方案往往难以满足实际应用中对高可用性、稳定性和自动化监控的要求。如何构建一个既能应对多种反爬策略,又能在异常情况下自动恢复、实时…...
picomax 中 rkipc 的main.c文件分析
main函数 int main(int argc, char **argv) {//wait_key_event 这个进程的pidpthread_t key_chk;LOG_DEBUG("main begin\n");//luckfox-pico/project/app/rkipc/rkipc/common/common.c中//显示版本rkipc_version_dump();//设置信号signal(SIGINT, sig_proc);signal(…...
深入理解 JVM 的栈帧结构
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…...
[oeasy]python068_异常处理之后做些什么_try语句的完全体_最终_finally
068_异常处理之后做些什么_finally 异常处理之后做些什么_try语句的完全体_最终_finally 回忆上次内容 我们了解了 try 的细节 except 可以 捕获到异常 但报错比较简单 添加图片注释,不超过 140 字(可选) 游乐场里面的 报错 更全 更丰富 …...
数据库端性能测试优化案例
数据库端性能测试优化案例 数据库是系统性能的关键瓶颈之一,特别是在高并发、大数据量的场景下。以下是一些典型的数据库端性能测试优化案例,涵盖了查询优化、索引策略、连接池管理、分布式数据库设计等多个方面: 1. 案例:优化慢…...
如何实现使用DeepSeek的CV模型对管道内模糊、低光照或水渍干扰的图像进行去噪、超分辨率重建。...
要使用 DeepSeek 的 CV 模型对管道内模糊、低光照或水渍干扰的图像进行去噪、超分辨率重建,一般可以按照以下步骤实现: 1. 准备工作 1.1 获取 API 访问权限 首先,你需要从 DeepSeek 官方获取 API 访问权限和相应的 API 密钥。这通常需要在 De…...
PySide6学习专栏(四):用多线程完成复杂计算任务
如果计程序中要处理一个非常庞大的数据集中的数据,且数据处理计算很复杂,造成数据处理占用大量时间和CPU资源,如果不用多线程,仅在主进程中来处理数据,将会使整个程序卡死,必须采用多线程来处理这些数据是唯…...
神经网络八股(1)
1.什么是有监督学习,无监督学习 有监督学习是带有标签的,无监督学习是没有标签的,简单来说就是有监督学习的输入输出都是固定的,已知的,无监督学习输入是已知的,输出是不固定的,无监督学习是通…...
深度学习每周学习总结Y1(Yolov5 调用官方权重进行检测 )
🍨 本文为🔗365天深度学习训练营 中的学习记录博客Y1中的内容 🍖 原作者:K同学啊 | 接辅导、项目定制 ** 注意该训练营出现故意不退押金,恶意揣测偷懒用假的结果冒充真实打卡记录,在提出能够拿到视频录像…...
计算机视觉基础|从 OpenCV 到频域分析
一、引言 在当今数字化时代,图像处理已渗透到我们生活的方方面面,从日常使用的智能手机拍照美化,到医学领域的精准诊断,再到自动驾驶中的环境感知,其重要性不言而喻。在图像处理领域中,OpenCV 和频域分析&…...
74. 搜索二维矩阵(LeetCode 热题 100)
题目来源; 74. 搜索二维矩阵 - 力扣(LeetCode) 题目内容: 给你一个满足下述两条属性的 m x n 整数矩阵: 每行中的整数从左到右按非严格递增顺序排列。 每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &am…...
netcore libreoffice word转pdf中文乱码
一、效果 解决: cd /usr/share/fonts/ mkdir zhFont cd zhFont #windows系统C:\Windows\Fonts 中复制/usr/share/fonts/zhFont sudo apt update sudo apt install xfonts-utils mkfontscale mkfontdir #刷新字体缓存 fc-cache -fv #查看已安装的字体列表 fc-list :…...
qt-C++笔记之创建和初始化 `QGraphicsScene` 和 `QGraphicsView` 并关联视图和场景的方法
qt-C笔记之创建和初始化 QGraphicsScene 和 QGraphicsView 并关联视图和场景的方法 code review! 参考笔记 1.qt-C笔记之创建和初始化 QGraphicsScene 和 QGraphicsView 并关联视图和场景的方法 2.qt-C笔记之QGraphicsScene和 QGraphicsView中setScene、通过scene得到view、通过…...
OpenGL 01--构建GLFW、创建第一个工程、配置GLAD
一、OpenGL介绍 一般它被认为是一个API(Application Programming Interface, 应用程序编程接口),包含了一系列可以操作图形、图像的函数。然而,OpenGL本身并不是一个API,它仅仅是一个由Khronos组织制定并维护的规范(Specification)。 OpenGL规…...
【时时三省】(C语言基础)求多项式1-1/2+1/3-1/4+...+1/99-1/100的值 用C语言表示
山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 示例: 输出结果是 0.688172...
kafka-集群缩容
一. 简述: 当业务增加时,服务瓶颈,我们需要进行扩容。当业务量下降时,为成本考虑。自然也会涉及到缩容。假设集群有 15 台机器,预计缩到 10 台机器,那么需要做 5 次缩容操作,每次将一个节点下线…...
