C++ 实现 JSON 序列化和反序列化
大纲
前言
本文将介绍如何使用 nlohmann/json 库实现 C++ 的 JSON 序列化和反序列化。在网络编程中,常用的数据序列化格式包括 XML、JSON 和 Protobuf。在企业级项目中,Protobuf 被广泛采用,因其具备高效的压缩能力和低带宽占用。相同的数据内容,Protobuf 的体积约为 JSON 的 1/10、XML 的 1/20,极大提升了传输效率。尽管使用上相较 JSON 略显复杂,但在对性能和带宽要求较高的场景中,Protobuf 是更优的选择。
版本说明
本文使用各软件的版本如下表所示:
| 软件 | 版本 | 说明 |
|---|---|---|
| C++ 标准 | 11 | |
| nlohmann/json | 3.12.0 | Json 库,基于 C++ 开发,用于 Json 序列化和反序列化 |
| G++(GCC) | 12.2.0 | 建议使用 5.5、7.5 版本的 G++(GCC) 编译器 |
主流 JSON 库
RapidJSON
RapidJSON 是由腾讯开源的一个 C++ JSON 解析与生成库,以极速性能为核心特点。它是一个头文件库(Header-Only),无需编译、依赖少,适合对性能要求极高的项目。
主要特点:
- 超高速:极致优化的 JSON 解析与生成性能,是 C++ 中最快的 JSON 库之一。
- 零依赖、跨平台:纯 C++ 实现,无需依赖 STL(可选开启),适用于嵌入式系统。
- 严格遵循 JSON 标准:完全符合
RFC 7159/ECMA-404。 - 内存控制精细:支持自定义内存分配器,可用于嵌入式、游戏等内存敏感场景。
- 支持 SAX / DOM 双模式:可用于不同性能与易用性需求的场景。
安装方式:
- 只需将头文件直接复制到项目的
include目录中,然后引入即可:1
2
3
- 只需将头文件直接复制到项目的
适用场景:
- 性能要求高的场景:如游戏引擎、嵌入式设备、实时系统、交易系统等。
- 不需要 STL(可选开启)的轻量应用。
- 需要手动管理 JSON 内存、定制行为的专业用途。
注意事项:
- 相比
nlohmann/json,RapidJSON 更偏向底层和性能,使用复杂度更高。 - 如果追求易用性和语法糖,推荐使用
nlohmann/json。 - 如果追求极致性能和精细内存控制,RapidJSON 是首选。
- 相比
nlohmann/json
nlohmann/json 是一个非常流行的 C++ 开源 JSON 库,以其简洁易用、接口友好和现代 C++ 特性支持而著称。它的设计目标是让 JSON 的使用尽可能像标准容器(如 std::map 和 std::vector)一样自然,几乎可以零学习成本上手。
主要特点:
- 现代 C++ 风格:基于 C++11/14/17 编写,支持智能指针、范围
for循环、初始化列表等特性。 - 类似 STL 的接口:使用方式类似
std::map和std::vector。 - 单头文件:只需包含一个头文件
json.hpp,无须额外依赖。 - 支持多种数据类型:支持
int、float、bool、string、vector、map、自定义结构体等。 - 强大的序列化与反序列化:可以方便地将 JSON 转换为 C++ 对象,或将 C++ 对象转为 JSON。
- 格式美观的输出:支持格式化打印 JSON 数据。
- 严谨的测试:所有类都经过严格的单元测试,覆盖了 100% 的代码,包括所有特殊的行为。此外,还使用了 Valgrind 来检查是否有内存泄漏。
- 现代 C++ 风格:基于 C++11/14/17 编写,支持智能指针、范围
安装方式:
- 最简单的方式是只包含一个头文件:
1
2
using json = nlohmann::json; - 还可以使用包管理工具如:
- vcpkg:
vcpkg install nlohmann-json - Conan:
conan install nlohmann_json/3.11.2@
- vcpkg:
- 最简单的方式是只包含一个头文件:
使用建议
- 对于配置文件、网络通信、日志记录、REST API 开发等场景都非常适用。
- 特别注意:虽然功能强大,但在性能要求极高的场合(如高频交易)可能不如手写解析或使用高性能库(如 RapidJSON)。
使用 JSON 库
JSON 库安装
- (1) 在 GitHub 仓库 下载所需版本的
json.hpp头文件,然后将其拷贝到 C++ 项目的include目录中,如下图所示:

(2) 最简单的使用方式是只包含
json.hpp头文件1
2
using json = nlohmann::json;
JSON 序列化
JSON 序列化就是将需要打包的数据或者对象,直接转换成 JSON 字符串。
案例一
- 普通数据的序列化
1 |
|
程序运行输出的结果:
1 | {"id":[1,2,3,4,5],"msg":{"liu suo":"hello python","zhang san":"hello go"},"name":"zhang san"} |
案例二
- STL 容器的序列化
1 |
|
程序运行输出的结果:
1 | {"lanuage":[[1,"Go"],[2,"Rust"],[3,"Python"]],"list":[1,2,3]} |
案例三
- C++ 对象与 JSON 对象的转换
1 |
|
程序运行输出的结果:
1 | Person object to JSON object : { |
JSON 反序列化
当从网络接收到的字符串为 JSON 格式时,可以用 JSON 库直接反序列化取得数据或者直接反序列化出对象,甚至 STL 容器。
1 |
|
程序运行输出的结果:
1 | json string: {"animal":[[1,"Dog"],[2,"Cat"]],"id":[1,2,3,4,5],"language":["Go","Rust","Python"],"name":"zhang san"} |
