找回密码
 立即注册
首页 业界区 业界 C++中JSON序列化和反序列化的实现

C++中JSON序列化和反序列化的实现

馏栩梓 3 小时前
1. 引言

序列化(Serialization)是指将程序中的内存对象(如结构体、类实例、列表等)转换成一种可以存储或传输的格式(通常是字节流或文本)的过程。常见的序列化格式包括:

  • JSON(文本,人类可读)
  • XML
  • Protocol Buffers(二进制,高效)
  • MessagePack
  • YAML
  • 甚至自定义的二进制格式
反序列化(Deserialization)是序列化的逆过程:将序列化后的数据(如 JSON 字符串)重新转换回程序中的内存对象
2. 原因

那么,为什么需要序列化和反序列化呢?笔者的体会是不序列化/反序列化也行,只不过在进行相应的读取和写入操作的时候会非常繁琐。比如一个配置文件更新:
假设我们有一个博客系统的配置,包含站点标题、作者名、是否启用评论、默认封面地址等多个字段。如果不使用序列化机制,每次读取配置时,就得手动打开 JSON(或 YAML、INI)文件,逐行解析,判断每个字段是否存在、类型是否正确,再一一赋值给程序中的变量;而当用户修改了某个设置、需要保存回文件时,又得手动拼接字符串、处理引号转义、数组格式、缩进对齐……稍有不慎,就会生成格式错误的文件,导致程序下次启动失败。
更麻烦的是,一旦配置结构发生变化——比如新增一个 theme 字段,或者把 enableComments 拆成 enablePostComments 和 enablePageComments——我们就不得不同时修改读取逻辑、写入逻辑、默认值初始化、错误处理等多处代码,极易遗漏或出错。
而有了序列化和反序列化,这一切就变得简洁而可靠:定义好结构体(或类),注册对应的转换函数,一行代码就能从 JSON 构造出完整的配置对象,另一行代码就能把修改后的对象写回文件。字段增减只需调整结构体,读写逻辑几乎无需改动,既减少了重复劳动,也大大提升了健壮性和可维护性。
因此,序列化/反序列化并非“必须”,但它是对抗复杂性、提升开发效率和系统可靠性的重要工具。
3. 实现

3.1 示例

这里就举例实现一下 C++ 中 JSON 序列化和反序列化。如果要反序列化成 C++ 可以使用的内存对象,最好的数据容器就是 struct 。当然 class 也可以,不过我们都知道 struct 和 class 的区别:struct 的成员一般默认是公有的,而 class 的成员一般默认是私有的。因此,struct 适合以数据成员为主的,比较简单的对象;class 适合以方法成员为主的,比较复杂的对象。
笔者使用 nlohmann/json 中序列化/反序列化一个表达博客的数据对象:
BlogMeta.h
  1. #include <nlohmann/json.hpp>
  2. #include <string>
  3. #include <vector>
  4. #include "PostStats.h"
  5. namespace DataTransfer {
  6. /// @brief 一篇博客的元数据
  7. struct BlogMeta {
  8.   std::string id;
  9.   std::string title;
  10.   std::string summary;
  11.   std::string createdTime;
  12.   std::string updatedTime;  
  13.   std::string coverAddress;
  14.   int64_t isDraft;
  15.   std::vector<std::string> tagNames;
  16.   std::vector<std::string> categoryNames;
  17.   PostStats postStats;
  18.   // 提供序列化接口
  19.   friend void to_json(nlohmann::json& j, const BlogMeta& s);
  20.   // 提供反序列化接口
  21.   friend void from_json(const nlohmann::json& j, BlogMeta& s);
  22. };
复制代码
BlogMeta.cpp
  1. #include "BlogMeta.h"
  2. #include "Util/GetTime.h"
  3. namespace DataTransfer {
  4. // 提供序列化接口
  5. void to_json(nlohmann::json& j, const BlogMeta& s) {
  6.   j = nlohmann::json{{"id", s.id},
  7.                      {"title", s.title},
  8.                      {"summary", s.summary},
  9.                      {"createdTime", s.createdTime},
  10.                      {"updatedTime", s.updatedTime},
  11.                      {"coverAddress", s.coverAddress},
  12.                      {"isDraft", s.isDraft},
  13.                      {"tagNames", s.tagNames},
  14.                      {"categoryNames", s.categoryNames},
  15.                      {"postStats", s.postStats}};
  16. }
  17. // 提供反序列化接口
  18. void from_json(const nlohmann::json& j, BlogMeta& s) {
  19.   s.id = j.at("id").get<std::string>();
  20.   s.title = j.at("title").get<std::string>();
  21.   s.summary = j.at("summary").get<std::string>();
  22.   s.createdTime = j.at("createdTime").get<std::string>();
  23.   s.updatedTime =
  24.       j.value("updatedTime", Util::GetCurrentTime());  //提供默认值,增加稳定性
  25.   s.coverAddress = j.at("coverAddress").get<std::string>();
  26.   s.isDraft = j.at("isDraft").get<int64_t>();
  27.   s.tagNames = j.at("tagNames").get<std::vector<std::string>>();
  28.   s.categoryNames = j.at("categoryNames").get<std::vector<std::string>>();
  29.   s.postStats = j.at("postStats").get<PostStats>();
  30. }
  31. }  // namespace DataTransfer
复制代码
其中 to_json / from_json 就是对应的 序列化 / 反序列化接口。只需要填充这一对接口,就可以通过赋值运算符=实现自动序列化和反序列化:
[code]#include #include #include "BlogMeta.h"  // 包含你的 BlogMeta 定义int main() {    using namespace DataTransfer;    using json = nlohmann::json;    // ----------------------------    // 1. 创建一个 BlogMeta 对象(内存中的数据)    // ----------------------------    BlogMeta blog;    blog.id = "blog-001";    blog.title = "深入理解 C++ 序列化";    blog.summary = "本文介绍如何使用 nlohmann/json 进行安全高效的序列化。";    blog.createdTime = "2025-12-22T10:00:00Z";    blog.updatedTime = "2025-12-22T17:00:00Z";  // 可省略,反序列化时会用默认值    blog.coverAddress = "/images/cpp_serialization.jpg";    blog.isDraft = 0;    blog.tagNames = {"C++", "JSON", "Serialization"};    blog.categoryNames = {"rogramming", "Tutorial"};    blog.postStats = {1200, 85, 23};    // ----------------------------    // 2. 序列化:BlogMeta → JSON    // ----------------------------    json j = blog;  // 自动调用 to_json    std::cout

相关推荐

您需要登录后才可以回帖 登录 | 立即注册