std::unordered_map 无内置 json 序列化能力,c++20 亦未添加;需手动遍历键值对构造 json,常见错误是误以为可直接用 std::cout 输出合法 json。

std::unordered_map 没有内置 JSON 序列化能力
标准库的 std::unordered_map 不提供 to_json() 或类似接口,C++20 也没加。想导出 JSON,必须手动遍历键值对,拼成 JSON 结构——不是“调个函数就行”的事。
常见错误现象:std::cout 编译失败;用 <code>nlohmann::json 直接构造 json j = my_map; 会触发编译错误(除非你特化了 adl_serializer)。
- 必须显式告诉 JSON 库每个 key 是什么类型、value 怎么映射(比如
int、std::string、嵌套std::map) - 如果 value 是自定义类型,还得额外写序列化逻辑
- key 必须是字符串(JSON object 的 key 只能是 string),而
std::unordered_map的 key 可以是int、std::pair等——这时必须先转成std::string
用 nlohmann/json 最简可行路径
nlohmann/json 是目前最轻量、兼容性最好、语法最直白的 C++ JSON 库。它支持直接从 std::map 构造 object,但对 std::unordered_map 需要一层适配。
实操建议:
- 头文件只加
#include <nlohmann></nlohmann>,无需链接 .lib - 把
std::unordered_map<:string t></:string>当作基础场景,T 支持int、double、std::string、std::vector、其他std::unordered_map(递归) - 别用
json::parse()去反向构造,直接用初始化列表或赋值
示例(导出到文件):
#include <nlohmann>
#include <fstream>
#include <unordered_map>
using json = nlohmann::json;
std::unordered_map<:string std::string> data = {
{"host", "localhost"},
{"port", "8080"},
{"debug", "true"}
};
json j(data); // ✅ 可行:key 是 string,value 是基本类型
std::ofstream("config.json")
<h3>key 不是 string 时必须手动转换</h3>
<p>一旦 <code>std::unordered_map</code> 的 key 是 <code>int</code>、<code>size_t</code> 或自定义结构,<code>json j(map)</code> 会编译失败——JSON 规范不允许非字符串 key。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2823" title="C++14"><img
src="https://img.php.cn/upload/manual/001/431/639/6ac8b33c327c4749.png" alt="C++14" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="overflowclass">C++14</a>
<p class="overflowclass">C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。</p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<p>使用场景:配置项用序号做 key(如 <code>std::unordered_map<int std::string></int></code> 表示日志级别映射),或用枚举做 key。</p>
<ul>
<li>必须遍历 map,把 key 转成 <code>std::string</code>(例如 <code>std::to_string(k)</code> 或查表)</li>
<li>不能依赖自动推导;<code>json::object()</code> 构造器不接受非 string key 的 initializer_list</li>
<li>性能影响小,但代码多 3–5 行;别试图用宏或模板隐去转换逻辑,可读性反而下降</li>
</ul>
<p>示例(int key → string key):</p>
<pre class="brush:php;toolbar:false;">
std::unordered_map<int std::string> codes = {{404, "Not Found"}, {500, "Internal Error"}};
json j;
for (const auto& [k, v] : codes) {
j[std::to_string(k)] = v; // ⚠️ key 强制转 string
}
std::ofstream("codes.json")
<h3>写入文件前务必检查 value 是否可 JSON 化</h3>
<p><code>nlohmann::json</code> 对不可序列化类型(如 <code>std::function</code>、裸指针、<code>std::thread</code>)会在运行时报错或静默丢弃字段,而不是编译报错。</p>
<p>容易踩的坑:</p>
<ul>
<li>value 是 <code>std::shared_ptr<t></t></code>:默认不支持,需自定义 <code>adl_serializer</code>,否则整个 entry 被跳过</li>
<li>value 含二进制数据(如 <code>std::vector<uint8_t></uint8_t></code>):直接塞进去会变成 base64?不会——它会被当作数字数组,可能不符合预期</li>
<li>浮点数精度丢失:默认 <code>dump()</code> 保留 17 位有效数字,但若原始值是 <code>float</code>,建议先转 <code>double</code> 再存</li>
</ul>
<p>安全做法:导出前用 <code>static_assert</code> 或单元测试验证 value 类型是否在已知支持集合内,尤其在多人协作项目中。</p>
<p>复杂点在于,没有银弹——每个业务场景的 value 类型组合不同,适配逻辑得跟着变。别指望一份通用模板覆盖所有 case,老老实实按需处理 key 转换和 value 序列化边界。</p></int>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!









