引入
在之前的讨论中,我们深入探讨了序列化与反序列化的概念。对于基于 TCP 协议通信的双方,由于 TCP 是面向字节流的,发送数据前通常需要定义一种结构化数据来描述内容。在 C++ 中,这通常表现为对象或结构体。然而,直接将结构体内存中的字节原样发送会引发字节序和内存对齐问题,不同平台或编译器可能导致解析错误。
因此,我们需要借助序列化。序列化是指将结构化数据按预定规则转换为连续字节流,目的是屏蔽平台差异,使不同平台的进程能统一解析该字节流。序列化主要分为文本序列化与二进制序列化。
文本序列化将数据转换为字符串,本质也是连续字节流,不存在字节序问题,但传输体积较大且解析开销高。二进制序列化直接发送原始二进制数据,体积小、解析快,但人类难以阅读。在实际开发中,成熟的第三方库通常能提供更完善的处理方案。
本文重点介绍广泛应用的文本序列化格式——JSON,并在此基础上,结合 Linux 网络编程,从零手搓一个支持 JSON 交互的 Web 计算器服务器。
JSON 基础与实践
JSON(JavaScript Object Notation)是一种轻量级、基于文本、人类可读的数据交换格式。它源于 JavaScript,但已跨语言通用。JSON 本质上符合规范的字符串,支持整型、浮点型、布尔型、字符串、对象及数组等类型。
在 C++ 中,常用的 JSON 库包括 json.hpp(即 nlohmann/json)。它是一个头文件库,无需编译安装,只需将其源码放入项目目录即可使用。
基本操作
json 类位于 nlohmann 命名空间内。创建对象主要有两种方式:列表初始化或直接赋值。
#include "json.hpp"
#include <iostream>
using json = nlohmann::json;
int main() {
// 方式一:列表初始化
json j1 = {{"name", "WZ"}, {"age", 20}};
// 方式二:直接赋值(推荐,更符合容器习惯)
json j2;
j2["name"] = "WZ";
j2["age"] = 20;
std::cout << j1.dump() << std::endl; // 紧凑格式
std::cout << j1.dump(2) << std::endl; // 格式化输出,缩进 2 格
return 0;
}
dump() 函数用于序列化,返回 std::string。不传参数时生成紧凑格式;传入整数参数则进行格式化缩进。注意,生产环境中通常避免缩进以减少传输体积。
对于数组,同样支持列表初始化或 添加元素。访问和修改字段则通过重载的 运算符实现,这与标准库容器的使用习惯一致。


