应采用“数据结构与序列化协议解耦”设计:定义统一 serialize(Serializer& s) 接口,由 JsonSerializer、BinarySerializer、YamlSerializer 等子类实现具体格式逻辑,字段映射、配置策略集中管控,避免硬编码多套序列化函数。
怎么让同一个C++类支持JSON、二进制、YAML三种序列化格式?
靠硬编码三套序列化逻辑,维护成本高、易出错。真正可行的路是把「数据结构」和「序列化协议」解耦——用统一的数据中间表示(比如
或自定义
),再按需绑定不同后端。
常见错误是直接在类里写
、
、
三个函数,结果字段增删时总漏改一个,测试也难覆盖全路径。
推荐做法:定义一个
成员函数,只描述字段名与值的映射关系;所有格式由外部
子类实现(如
、
、
)
字段顺序、默认值、忽略策略等配置,统一收口到
构造参数或配置对象里,不散落在各处
注意
在 C++17+ 可用,但跨平台项目若需兼容旧编译器,建议用
或轻量级
实现
JSON 和 YAML 序列化能共用同一套解析逻辑吗?
能,但仅限于“读取”阶段——只要底层都转成键值对结构(比如
),上层业务代码就完全不用感知格式差异。但写入时不能混用:YAML 支持锚点、折叠块、时间戳等 JSON 没有的特性,强行用 JSON 库写 YAML 会丢信息或报错。
典型坑是用
加载 YAML 文件(它不支持),或用
解析 JSON 字符串(它要求严格 YAML 语法)。
立即学习
“
C++免费学习笔记(深入)
”;
读取时:用
加载 YAML 或 JSON 都行(它兼容 JSON 子集),但需调用
而非
——后者对换行/缩进更敏感
写入时:JSON 必须用
或
;YAML 必须用
;二者输出接口不兼容,别试图桥接
如果项目只读不写 YAML,可全程用
统一处理,省去格式判断逻辑
二进制序列化怎么保证跨平台兼容性?
核心问题是字节序、对齐、浮点表示、字符串编码。用
直拷结构体,在 x86 和 ARM 上可能因对齐规则不同而读错;float/double 在部分嵌入式平台不是 IEEE 754,直接序列化会失真。
C知道
CSDN推出的一款AI技术问答工具
下载
常见错误是把
当作序列化长度,没考虑 padding 字节;或用
写内存,结果在不同编译器下字段偏移不一致。
必须手动控制字段顺序和对齐:用
或
消除 padding,且所有字段声明顺序固定
整数一律转为网络字节序:
/
处理
/
,避免大小端问题
浮点数不直接序列化,转成
/
再存(用
或 union),确保位模式一致
字符串用变长前缀(
+
),别依赖 null-terminator
如何动态切换序列化格式而不改业务代码?
关键在抽象出
接口,并用工厂或配置驱动实例创建。比如从配置文件读到
,就 new 一个
;换成
就换实例——业务层只调用
,完全无感。
容易被忽略的是:不同格式的错误处理语义不同。JSON 解析失败抛
,二进制校验失败可能返回
,YAML 加载失败又可能是
。统一异常体系必须提前设计好。
工厂函数返回
,构造时传入配置对象(如
)
所有
子类必须实现
方法(返回
、
等),方便日志和调试
不要在构造
时打开文件或连接网络——延迟到
或
调用时才做 I/O,否则初始化失败会导致整个模块不可用
最麻烦的其实是类型系统边界:比如 YAML 允许
、
、
,JSON 只有
,二进制通常只认基本类型。这些语义鸿沟没法自动填平,得在配置里显式声明字段是否可空、是否带单位、是否有序列化约束——漏掉一条,上线后就可能 crash。
std::map<:string std::any>VariantMapto_json()to_binary()to_yaml()serialize(Serializer& s)SerializerJsonSerializerBinarySerializerYamlSerializerSerializerstd::anyboost::variantvariantstd::map<:string variant>nlohmann::jsonyaml-cppyaml-cppYAML::LoadFile()YAML::Load()nlohmann::jsonrapidjsonyaml-cppyaml-cppmemcpysizeof(MyStruct)reinterpret_cast(&obj) #pragma pack(1)alignas(1)htons()htonl()uint16_tuint32_tuint32_tuint64_tstd::bit_castuint32_t lenchar data[len]Serializerformat: "binary"BinarySerializer"json"s.serialize(obj)json::parse_errorstd::errc::invalid_argumentYAML::ParserExceptionstd::unique_ptrSerializerConfig{.endian = LITTLE, .use_crc = true}Serializername()"json""binary"Serializerserialize()deserialize()null!!timestamp!!setnull