ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

如何用 NLOHMANN_JSON_SERIALIZE_ENUM 把 C++ 枚举序列化为 JSON 字符串而不是整数

如何用 NLOHMANN_JSON_SERIALIZE_ENUM 把 C++ 枚举序列化为 JSON 字符串而不是整数 如何用 NLOHMANN_JSON_SERIALIZE_ENUM 把 C 枚举序列化为 JSON 字符串而不是整数【免费下载链接】jsonJSON for Modern C项目地址: https://gitcode.com/GitHub_Trending/js/json在 JSON for Modern Cnlohmann/json中枚举默认会被序列化为 JSON 整数。如果后续修改了枚举值顺序或整数值之前写入 JSON 的数据反序列化时可能得到错误的枚举成员。NLOHMANN_JSON_SERIALIZE_ENUM宏可以为每个枚举成员指定一个 JSON 字符串表示让序列化结果稳定可读。本文按文档给出的完整示例演示如何配置该宏、如何序列化/反序列化以及如何验证结果。宏自 3.4.0 版本起可用。为什么默认行为会出问题文档说明默认行为枚举值按整数值写入 JSON。一旦枚举被修改或重新排序之后反序列化同一份 JSON 数据可能得到未定义的结果或者与原始意图不同的枚举值。为每个枚举显式声明字符串映射后JSON 中保存的是你指定的字符串不再依赖整数值。准备条件已按项目安装方式获得nlohmann/json.hpp头文件示例中通过#include nlohmann/json.hpp引用枚举类型已定义可以是传统enum也可以是 C11enum class文档示例两种都覆盖一个关键前提宏必须声明在枚举类型所在的命名空间内可以是全局命名空间否则库找不到它会回退到整数序列化。而且在使用这些转换的每个地方宏都必须可见即相应的头文件已包含。基本用法声明字符串映射以下代码来自 示例文件定义了两个枚举并分别为它们声明字符串映射。注意两个NLOHMANN_JSON_SERIALIZE_ENUM都写在namespace ns内与枚举定义同命名空间#include iostream #include nlohmann/json.hpp using json nlohmann::json; namespace ns { enum TaskState { TS_STOPPED, TS_RUNNING, TS_COMPLETED, TS_INVALID -1 }; NLOHMANN_JSON_SERIALIZE_ENUM(TaskState, { { TS_INVALID, nullptr }, { TS_STOPPED, stopped }, { TS_RUNNING, running }, { TS_COMPLETED, completed } }) enum class Color { red, green, blue, unknown }; NLOHMANN_JSON_SERIALIZE_ENUM(Color, { { Color::unknown, unknown }, { Color::red, red }, { Color::green, green }, { Color::blue, blue } }) } // namespace ns参数含义来自宏的 API 文档type要序列化/反序列化的枚举类型名conversion...枚举成员与 JSON 表示组成的对以逗号分隔个数不限。宏的效果是在命名空间中添加两个函数templatetypename BasicJsonType inline void to_json(BasicJsonType j, const type e); templatetypename BasicJsonType inline void from_json(const BasicJsonType j, type e);序列化与反序列化// 枚举 - JSON 字符串 json j_stopped ns::TS_STOPPED; json j_red ns::Color::red; // JSON 字符串 - 枚举 json j_running running; json j_blue blue; auto running j_running.getns::TaskState(); auto blue j_blue.getns::Color();直接赋值json j 枚举值触发to_json得到的 JSON 值就是映射表中对应的字符串反向转换通过getENUM_TYPE()触发from_json参数是包含对应字符串的 JSON 值。验证结果示例程序的完整输出以下为文档示例输出来自 示例输出文件ns::TS_STOPPED - stopped, ns::Color::red - red running - 1, blue - 2 3.14 - -1, 3.14 - 3判断要点第一行说明序列化方向生效TS_STOPPED输出为字符串stopped而不是整数0第二行说明反序列化生效字符串running还原为TS_RUNNING打印其整数值 1blue还原为Color::blue整数值 2第三行演示了未定义 JSON 值的回退行为3.14不匹配任何映射getns::TaskState()返回映射表中第一对TS_INVALID整数值 -1getns::Color()返回Color::unknown整数值 3。因此第一对映射实际上兼作默认值文档明确要求慎重选择这个默认对。示例中用{ TS_INVALID, nullptr }作为哨兵TS_INVALID的 JSON 表示是nullptr即它本身不会被序列化成合法字符串只承担未识别输入时返回它的角色。一个枚举成员映射多个字符串映射表允许同一个枚举成员出现多次。规则是无论序列化还是反序列化都返回从表顶开始第一个匹配的转换。文档示例示例代码NLOHMANN_JSON_SERIALIZE_ENUM(Color, { { Color::unknown, unknown }, { Color::red, red }, { Color::green, green }, { Color::blue, blue }, { Color::red, rot } // a second conversion for Color::red })效果文档示例输出0 - red rot - 0 red - 0即Color::red序列化时总是得到red第一个出现的转换而rot可以作为反序列化为Color::red的别名。这个机制适合为已有数据保留旧字符串名。需要严格报错时用 STRICT 变体默认宏对未识别的 JSON 值静默回退到第一个映射对。文档提供了NLOHMANN_JSON_SERIALIZE_ENUM_STRICT()3.13.0 起行为与默认宏相同区别是遇到未定义输入时抛出异常而不是回退序列化一个未列入映射表的枚举值时抛异常通过getENUM_TYPE()反序列化匹配不到任何转换的 JSON 值时抛异常异常类型为out_of_range.410消息形如enum value out of range for type。适合在数据合法性必须可检查的场景替换默认宏两个宏的宏体结构一致替换时保持在枚举命名空间内声明的前提不变。可选禁止整数序列化回退如果想让整个工程彻底不允许未声明宏的枚举按整数进出 JSON可以把JSON_DISABLE_ENUM_SERIALIZATION定义为1默认为0见 JSON_DISABLE_ENUM_SERIALIZATION。此时没有提供to_json/from_json的枚举在解析或序列化时直接编译错误文档示例展示的配合方式是仍用NLOHMANN_JSON_SERIALIZE_ENUM提供字符串转换代码可以正常编译运行该宏对 unscoped 和 scoped 枚举都生效使用 CMake 构建时也可以用 CMake 选项JSON_DisableEnumSerialization默认OFF来控制它会相应地定义该宏。小结与限制宏必须放在枚举所在命名空间、且在使用处可见否则静默回退到整数序列化——这是文档列出的首要前提映射表第一对是未识别 JSON 值的回退目标需要显式选定想要异常而非回退时改用 STRICT 变体重复条目以表顶第一个匹配为准以上能力均来自 Specializing enum conversion 与宏的 API 文档可对照示例源码验证行为。【免费下载链接】jsonJSON for Modern C项目地址: https://gitcode.com/GitHub_Trending/js/json创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表