nlohmann/json是C++事实标准JSON库,纯头文件使用,需正确包含json.hpp并用parse_file()读文件、at()安全访问字段,注意UTF-8编码与异常处理。

用 nlohmann/json 读取 JSON 文件最省事,但得先装好头文件
不推荐手写解析器,C++ 标准库至今没原生 JSON 支持。第三方里 nlohmann/json 是事实标准:头文件即用、语法接近 Python、错误提示还算友好。它不是系统级依赖,不用编译安装,下载单个 json.hpp 放进项目目录就能 #include。
常见错误现象:undefined reference to `nlohmann::detail::parse_error::create —— 这是误用了源码编译方式(比如把 .cpp 当成 .hpp 引入),nlohmann/json 必须纯头文件使用,不能链接对象文件。
- 确保
#include <nlohmann/json.hpp>路径正确,不是<json.hpp> - 如果用 CMake,别写
find_package(nlohmann_json)后又手动加头文件路径,容易冲突 - C++17 起建议开启
-std=c++17,否则某些嵌套结构推导可能报错
json::parse() 和 json::parse_file() 别混用
json::parse_file() 是 v3.10.0 才加的便利函数,之前版本只有 json::parse()。前者直接读磁盘文件并解析,后者只处理字符串或流——很多人卡在这儿:传了个文件路径字符串给 json::parse(),结果解析出一个带斜杠的字符串对象,不是 JSON 结构。
使用场景:配置文件加载、静态数据初始化;性能上 parse_file() 内部做了内存映射优化,比先 std::ifstream 读全再 parse() 略快,但差异通常可忽略。
立即学习“C++免费学习笔记(深入)”;
- 安全起见,始终检查异常:
try { j = json::parse_file("config.json"); } catch (const json::parse_error& e) { /* 打印 e.what() */ } - 路径支持相对路径,但当前工作目录由运行环境决定,不是源码位置
- UTF-8 编码是硬性要求,含中文的文件必须保存为 UTF-8 无 BOM,否则抛
parse_error
访问嵌套字段时,operator[] 和 at() 行为完全不同
j["user"]["name"] 看着自然,但它是“宽松访问”:键不存在就自动创建空对象,后续赋值才生效。而 j.at("user").at("name") 是严格访问,键缺失直接抛 out_of_range 异常。线上程序崩在 operator[] 上很常见——你以为读到了字段,其实只是新建了个空节点。
参数差异:两者都支持 string 和 int(数组索引),但 at() 不接受隐式类型转换,比如 j.at(0) 可以,j.at("0") 就不行。
- 配置读取、API 响应解析等关键路径,一律用
at()+try/catch - 临时调试或构建阶段可用
operator[],但别让它出现在条件判断里,比如if (j["data"]) {...}永远为真 - 检查字段是否存在用
j.contains("field"),不是j["field"].is_null()
中文乱码、浮点精度、大文件内存暴涨都是默认行为惹的祸
默认输出 JSON 会美化缩进、浮点数保留最多 17 位小数、字符串转义所有非 ASCII 字符——这些对调试友好,但对生产环境可能是坑。比如日志里打印 JSON,中文全变成 \u4f60\u597d;或者 3.141592653589793 被存成 3.1415926535897931 导致前后端比对失败。
大文件读取时,nlohmann/json 会一次性加载全部内容到内存,没有流式解析能力。100MB JSON 文件大概吃掉 300MB 内存(JSON 文本 + 解析后对象树)。
- 关闭 Unicode 转义:
j.dump(-1, ' ', false, json::error_handler_t::replace) - 控制浮点精度:
j.dump(2)表示小数点后 2 位,但注意这是格式化输出,不影响内部存储 - 超大文件(>10MB)考虑换
simdjson或rapidjson的 SAX 模式,nlohmann/json不支持
真正麻烦的是混合编码:Windows 记事本默认 ANSI,Linux 终端默认 UTF-8,跨平台部署时文件编码和程序预期不一致,错误信息里连 parse_error 都可能显示为方块字。这事没法靠代码兜底,得从 CI 流程里卡住文件编码。



















