第一部分:JSON 基础知识
📢 快速掌握 JSON!文章 + 视频双管齐下 🚀
如果你觉得阅读文章太慢,或者更喜欢 边看边学 的方式,不妨直接观看我录制的 JSON 课程视频!🎬 视频里会用更直观的方式讲解 JSON 的核心概念、实战技巧,并配有动手演示,让你更高效地掌握 JSON 的处理方法!
当然,如果你喜欢深度阅读,这篇文章会帮助你系统地理解 JSON,从基础到进阶!无论你选择哪种方式,最终目标都是让你成为 JSON 处理的高手!💪
🎥 点击这里观看视频 👉 视频链接
一:JSON 介绍
1.1 JSON 是什么?
- JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,主要用于前后端数据传输、配置文件存储、API 交互等。
- 它基于 JavaScript 语言的对象表示法,但与编程语言无关,因此被广泛应用于 C/C++、Python、Java、Go、Rust 等语言中。
1.2 JSON 的特点及优点
✅ 可读性强:JSON 采用 键值对(Key-Value) 结构,语法简单直观,易于人和机器解析。
✅ 轻量级:相比 XML,JSON 体积更小,解析速度更快。
✅ 跨语言兼容:JSON 可以在不同的编程语言之间交换数据,各种语言都支持 JSON 解析。
✅ 层次结构(嵌套):支持 数组、对象、嵌套数据结构,适合存储复杂数据。
✅ 无格式要求:不需要像 XML 那样定义模式(Schema),使用灵活。
1.3 JSON 与 XML 的对比
JSON 与 XML(Extensible Markup Language)都是常见的数据交换格式,以下是它们的区别:
对比项 | JSON | XML |
---|---|---|
数据结构 | 键值对(Key-Value) | 标签(Tag-Based) |
可读性 | 结构清晰,易理解 | 层级嵌套复杂 |
解析效率 | 解析速度快 | 解析速度慢 |
数据体积 | 体积小 | 体积较大 |
可扩展性 | 适用于结构化数据 | 适用于更复杂的数据格式 |
📌 JSON 与 XML 实例对比
✅ JSON 格式数据:
{
"person": {
"name": "张三",
"age": 25,
"hobbies": ["篮球", "足球"],
"sex":"男"
}
}
✅ XML 格式数据:
<person>
<name>张三</name>
<age>25</age>
<hobbies>
<hobby>篮球</hobby>
<hobby>足球</hobby>
</hobbies>
<sex>男</sex>
</person>
结论:
- JSON 结构更加紧凑,更适合数据交换。
- XML 适合文档存储(如配置文件、HTML、RSS 订阅等)。
二:JSON 的数据结构和语法
2.1 JSON 的数据结构
- JSON 由 对象(Object) 和 数组(Array) 组成,核心元素包括:
- 对象(使用
{}
表示,存储键值对) - 数组(使用
[]
表示,存储多个值) - 值类型(支持
字符串
、数值
、布尔值
、null
、对象
、数组
)
- 对象(使用
JSON 支持以下六种数据类型:
数据类型 | 示例 | 描述 |
---|---|---|
对象(Object) | { "name": "张三", "age": 25 } | 键值对的集合,类似于 C++ 的 std::map 或 Python 的字典 |
数组(Array) | [1, 2, 3, 4] | 有序的值列表,对应 C++ 的 std::vector 或 Python 的列表 |
字符串(String) | "hello" | 双引号包裹的文本数据, 必须使用双引号 "" ,不能使用单引号 |
数值(Number) | 123 ,3.14 | 整数或浮点数 |
布尔值(Boolean) | true ,false | 逻辑值 true 和 false |
空值(null) | null | 表示空对象 |
2.2 JSON 语法规则
JSON 数据的核心是键值对(Key-Value),其中:
- 键(Key)必须是字符串,且用双引号
""
包围。 - 值(Value)可以是字符串、数值、布尔值、数组、对象或
null
。 - 多个键值对之间用 逗号
,
分隔,对象用 大括号{}
包围,数组用 方括号[]
包围。 - 字符串 必须使用双引号
""
。
📌 示例:一个完整的 JSON 数据结构
{
"name": "Alice",
"age": 25,
"is_student": false,
"skills": ["C++", "Python", "JavaScript"],
"address": {
"city": "New York",
"zip_code": "10001"
},
"null":null
}
📌 解析该 JSON 结构:
name
:字符串"Alice"
age
:数值25
is_student
:布尔值false
skills
:数组["C++", "Python", "JavaScript"]
address
:嵌套对象,包含city
和zip
两个键值对
JSON 解析后相当于 C 语言的结构体:
struct Address {
char city[20];
char zip_code[10];
};
struct Person {
char name[20];
int age;
int is_student;
char* skills[3];
struct Address address;
};
2.3 JSON 语法规则(重要)
❌ 错误示例(常见语法错误):
{
name: "张三", // ❌ 错误:键名必须使用双引号
"age": 25,
"hobbies": [ "篮球", "足球", ], // ❌ 错误:数组最后一个元素后不能有逗号
"address": { "city": "上海", "zip_code": "200000", } // ❌ 错误:对象最后一个键值对后不能有逗号
}
✅ 正确格式:
{
"name": "张三",
"age": 25,
"hobbies": ["篮球", "足球"],
"address": { "city": "上海", "zip_code": "200000" }
}
三:JSON 的实际应用场景
JSON 适用于多种编程场景,常见应用如下:
3.1 Web API 数据交互
服务器通过 REST API / GraphQL 以 JSON 格式返回数据,前端(Vue、React)解析 JSON 并展示(如 GET
、POST
请求)。
JSON 替代 XML,成为 API 传输的主流数据格式。
📌 示例:前端 JavaScript 发送 JSON 请求到服务器
fetch("https://api.example.com/user", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "Alice", age: 25 })
})
.then(response => response.json())
.then(data => console.log(data));
3.2 配置文件存储
JSON 用于软件、Web 服务器、数据库的 配置文件,如 config.json
。
📌 示例:Web 服务器 Nginx 的配置
{
"server": "localhost",
"port": 8080,
"enable_ssl": true
}
3.3 数据存储与日志管理
JSON 可用于存储日志、数据缓存,如 NoSQL 数据库(MongoDB)使用 JSON 作为存储格式。
📌 MongoDB 文档存储示例
{
"_id": "user123",
"username": "Alice",
"email": "alice@example.com"
}
3.4 机器学习与日志分析
- 训练数据、日志文件等大量使用 JSON 进行数据存储。
- 便于后续分析和处理。
JSON 适用于存储服务器日志:
{
"timestamp": "2024-02-09T12:30:45Z",
"level": "ERROR",
"message": "数据库连接失败",
"details": {
"host": "db.example.com",
"port": 3306
}
}
日志分析工具可以轻松解析 JSON 日志,进行故障排查!
3.5 物联网(IoT)
-
IoT 设备通过 JSON 格式传输传感器数据。
-
示例:
{ "device_id": "sensor_001", "temperature": 22.5, "humidity": 60 }
四:JSON 解析和生成
3.1 JSON 解析(Parsing)和生成(Serialization)概述
- 解析(Parsing):把 JSON 字符串转换为可操作的数据结构(C 结构体或 C++ 类)。
- 序列化(Serialization):把 C/C++ 数据结构转换为 JSON 字符串,便于存储和传输。
3.2 JSON 在不同编程语言中的支持情况
-
C 语言处理 JSON 需要使用专门的解析库(如 cJSON)。
-
C++ 提供多个 JSON 库(RapidJSON、JsonCpp、nlohmann/json等)。
3.3 JSON 解析的基本流程
- 步骤 1:读取 JSON 数据(从字符串或文件)。
- 步骤 2:解析 JSON 并存入内存中的数据结构。
- 步骤 3:访问 JSON 数据(读取键值、遍历数组)。
- 步骤 4:修改 JSON 数据(添加/删除键值对)。
- 步骤 5:将数据重新序列化为 JSON 字符串,供存储或网络传输。
示例代码(伪代码,后续库会具体实现)
char* json_string = "{ \"name\": \"张三\", \"age\": 25 }";
JsonObject obj = json_parse(json_string);
printf("姓名: %s\n", json_get_string(obj, "name"));
json_set_number(obj, "age", 26);
char* new_json_string = json_serialize(obj);
printf("修改后的 JSON: %s\n", new_json_string);
3.4 C/C++ 解析 JSON 的常见库对比
- cJSON、RapidJSON、JsonCpp、JSON for Modern C++
3.4.1 cJSON📌
-
概述
-
cJSON 是一个轻量级的 C 语言实现的 JSON 库,专为嵌入式设备和资源受限的环境设计。
-
它非常简洁,适合简单的 JSON 数据解析任务。
-
-
特点
-
纯 C 实现:没有任何外部依赖,适用于嵌入式开发和低资源环境。
-
API 简单直观:易于上手,接口简单,适合 C 开发者。
-
内存管理:需要手动管理内存,易产生内存泄漏问题。
-
-
性能表现
- 在单线程和小数据量的情况下,cJSON 解析性能较好,但在处理大量数据时,性能会略显不足。
-
使用场景
-
嵌入式设备开发(如 IoT)
-
需要轻量化的 JSON 解析任务
-
-
优缺点
优点
- 轻量级:非常适合资源受限的嵌入式系统。
- 易用性高:API 设计简洁,快速上手。
- 没有外部依赖:纯 C 实现,不依赖其他库。
缺点
- 性能限制:在大数据量处理上,性能和内存管理上有一定的瓶颈。
- 内存管理手动:需要开发者自己管理内存,容易引入内存泄漏问题。
3.4.2 RapidJSON📌
-
概述
-
RapidJSON 是一个 C++ 实现的高性能 JSON 解析库,强调 速度 和 低内存使用,支持 SAX 和 DOM 解析方式。
-
它是 C++ 中最受欢迎的 JSON 解析库之一,适用于高性能的 JSON 解析场景。
-
-
特点
-
C++ 实现:支持现代 C++ 语法和标准,适用于 C++ 开发者。
-
高性能:在解析速度和内存占用方面,尤其是在大数据量时具有明显优势。
-
流式解析(SAX):支持流式解析,可以在解析大 JSON 文件时避免内存占用过高。
-
-
性能表现
-
解析速度:在大数据量 JSON 解析时,RapidJSON 表现出色,比大多数 C++ 库要快。
-
内存使用:内存使用高效,适合需要优化性能的场景。
-
-
使用场景
-
高性能计算和大数据处理
-
日志解析
-
金融、游戏、科学计算等需要高效解析的大型 JSON 数据
-
-
优缺点
优点
- 高性能:在大数据量的解析上,表现比其他库更好。
- 支持流式解析:适合大文件的逐步解析,内存消耗低。
- 支持标准 C++:支持 C++11 和以上标准,现代化的接口。
缺点
- 不支持动态内存管理:需要开发者自己处理内存分配与管理。
- 接口复杂:与其他库相比,API 比较复杂,上手稍有难度。
3.4.3 JsonCpp📌
-
概述
-
JsonCpp 是一个功能强大的 C++ JSON 解析库,旨在提供一种简单的接口来操作 JSON 数据。
-
适用于中到大型 C++ 项目的 JSON 数据解析与操作。
-
-
特点
-
C++ 实现:适用于 C++ 项目,API 风格符合 C++ 的习惯。
-
支持读取和写入 JSON:不仅可以解析 JSON,还可以方便地将数据写回 JSON 格式。
-
与 STL 兼容:可以直接与 C++ 的
std::string
和std::vector
等数据结构进行交互。
-
-
性能表现
-
解析速度:性能中等,适合大多数应用场景,尤其是中等规模的数据解析。
-
内存消耗:内存使用较为稳定,但与 RapidJSON 相比,速度稍慢。
-
-
使用场景
-
配置文件解析
-
常见桌面应用的数据存储
-
需要 JSON 读写操作的场景
-
-
优缺点
优点
- API 易用性:符合 C++ 风格的接口,易于开发者上手。
- 功能全面:除了 JSON 解析,还支持 JSON 数据的生成与修改。
- STL 兼容性强:可以与 C++ 标准库的容器和数据结构无缝对接。
缺点
- 性能一般:在大数据量处理时,解析速度较慢,内存消耗较高。
- 库体积较大:相比其他库,JsonCpp 的体积稍大,可能不适合嵌入式设备。
3.4.4 JSON for Modern C++📌
-
概述
-
JSON for Modern C++(由 nlohmann/json 提供)是一个流行的 C++ JSON 库,利用 C++11 特性,如
std::string
、std::vector
等,提供直观的 JSON 处理接口。 -
支持与标准 C++ 容器类型(如
std::map
、std::vector
)的无缝集成。
-
-
特点
-
C++11 风格 API:现代化的接口,支持
std::vector
、std::map
等 C++ 标准库容器。 -
JSON 数据转换:提供简洁的方式将 C++ 对象转换为 JSON,反之亦然。
-
简洁易用:API 设计现代且简洁,代码量少,易于理解。
-
-
性能表现
-
解析速度:与 RapidJSON 相比稍慢,但仍适用于大多数应用场景。
-
内存占用:内存使用高效,适合较大数据集。
-
-
使用场景
-
现代 C++ 项目
-
配置文件管理
-
Web 开发中前后端数据交互
-
-
优缺点
优点
- 易用性高:简洁的 API,适合现代 C++ 开发者。
- 兼容性强:与标准 C++ 容器和 STL 兼容。
- 支持转换 C++ 对象和 JSON:可以轻松将 C++ 对象序列化为 JSON,反之亦然。
缺点
- 性能相对较低:解析大规模 JSON 数据时,性能可能不如 RapidJSON。
- 对旧版 C++ 不友好:要求至少 C++11。
3.4.5 总结📌
库 | 语言 | 性能 | 使用场景 | 优点 | 缺点 |
---|---|---|---|---|---|
cJSON | C | 中等 | 嵌入式开发、轻量级应用 | 轻量级、无依赖 | 性能不佳、内存管理手动 |
RapidJSON | C++ | 高性能 | 大数据解析、日志、API | 快速、支持流式解析 | API 复杂、内存管理手动 |
JsonCpp | C++ | 中等 | 中型 C++ 项目、配置文件 | STL 兼容、功能全面 | 性能一般、库体积较大 |
JSON for Modern C++ | C++ | 中等 | 现代 C++ 项目、Web 应用 | 简洁易用、C++11 风格 | 性能较低、仅支持 C++11 以上 |
五:JSON 的性能优化策略
5.1 避免 JSON 过度嵌套
过度嵌套会 影响解析速度,应尽量 扁平化 JSON 结构。
❌ 差的 JSON 结构(深度嵌套)
{
"user": {
"profile": {
"details": {
"name": "Alice"
}
}
}
}
✅ 优化后(扁平化 JSON)
{
"user_name": "Alice"
}
5.2 使用流式解析(SAX 解析)
对于 大 JSON 文件,不要一次性加载到内存,而使用 流式解析(SAX 解析)。
📌 C++ 解析 JSON 时使用 RapidJSON 流式解析(节省内存)
#include "rapidjson/reader.h"
using namespace rapidjson;
class MyHandler : public BaseReaderHandler<UTF8<>, MyHandler> {
public:
bool String(const char* str, SizeType length, bool copy) {
printf("解析到字符串: %s\n", str);
return true;
}
};
int main() {
const char* json = "{\"name\":\"Alice\",\"age\":25}";
MyHandler handler;
Reader reader;
StringStream ss(json);
reader.Parse(ss, handler);
return 0;
}
5.3 常见问题分析与解决方案
问题 | 可能原因 | 解决方案 |
---|---|---|
JSON 解析失败 | 语法错误(如 , 结尾) | 使用 jsonlint 校验 JSON |
JSON 体积过大 | 包含大量冗余数据 | 优化 JSON 结构,减少嵌套 |
解析速度慢 | 使用 DOM 解析大文件 | 采用 流式解析(SAX) |
不支持 JSON 注释 | JSON 规范不允许注释 | 使用 // 伪注释字段或 YAML |