绝大多数新项目选 nlohmann/json:免编译、头文件即用、c++11 全平台兼容;jsoncpp 需手动编译且易遇链接/版本问题;旧项目勿强行迁移,嵌入式场景体积差异微小,读 json 文件必须用 binary 模式。

用 nlohmann/json 还是 jsoncpp?选库前先看这三点
绝大多数新项目直接用 nlohmann/json,它免编译、头文件即用、C++11 起全平台兼容,2026 年已成事实标准。jsoncpp 需要手动编译静态/动态库,Linux 下容易因 libjsoncpp.so 版本不匹配报 undefined symbol 错误,Windows 上更常遇到 LNK2019 找不到 Json::Reader::parse 实现——本质是链接时漏了 libjsoncpp.lib 或 CMake 没正确 target_link_libraries。
- 已有旧项目用 jsoncpp:别强行替换,
Json::Value和nlohmann::json语义差异大,迁移成本高 - 嵌入式或极端精简场景:jsoncpp 的二进制体积略小,但差距在百 KB 级,通常不构成决策依据
- 需要中文键名或 UTF-8 原生支持:两个库都支持,但 jsoncpp 默认不校验 BOM,读带
U+FEFF的文件可能静默失败
读 JSON 文件时,ifstream 必须加 std::ios::binary 吗?
必须加。不加会导致 Windows 下读取含换行的 JSON(比如用 StyledWriter 格式化过的)时,\r\n 被 ifstream 自动转成 \n,后续 Json::Reader::parse() 解析失败,报错类似 "invalid value" at line 1;nlohmann/json 虽然容错稍强,但遇到 BOM 或非 ASCII 字符仍可能解析出空对象。
-
std::ifstream ifs("config.json", std::ios::binary);是安全底线 - 读完后不用
ifs.seekg(0)回退——parse()内部会处理流位置 - 如果用
std::filesystem::read_bytes(C++17),则完全绕过流问题,但需自行转std::string_view
nlohmann::json::parse() 和 jsoncpp::Reader::parse() 的错误处理差异
两者都返回布尔值表示成功,但错误信息暴露程度天差地别:nlohmann 提供 json::parse_error 异常,能精确到第几行第几个字符;jsoncpp 只有 getFormattedErrorMessages() 返回字符串,且默认不开启详细模式,容易让开发者对着 "parse error" 空转。
- nlohmann 示例:
try { auto j = nlohmann::json::parse(ifs); } catch (const nlohmann::json::parse_error& e) { std::cerr - jsoncpp 必须显式启用:
reader.parse(ifs, root, false);第三个参数为false才输出完整错误上下文 - 线上环境别依赖
std::cout打印错误——JSON 解析失败往往发生在配置加载阶段,日志系统可能还没初始化
写 JSON 到文件时,格式化(pretty)和紧凑(compact)怎么选?
开发调试期无脑开 std::setw(2) 格式化;生产环境配置文件若被 Ansible/Chef 等工具 diff,紧凑模式可避免因空格/换行导致的误判;但注意:nlohmann 的 dump(2) 输出末尾带换行,jsoncpp 的 StyledWriter 不带——如果下游脚本用 head -n1 读首行,结果可能不一致。
立即学习“C++免费学习笔记(深入)”;
- nlohmann 写法:
ofs (显式补换行更可控) - jsoncpp 写法:
Json::StreamWriterBuilder wbuilder; wbuilder["indentation"] = " "; ofs - 别用
FastWriter存含中文的配置——它不转义 Unicode,终端显示可能乱码,且某些 shell 工具会截断
真正麻烦的从来不是读写本身,而是 JSON 键名拼错、类型强制转换(比如把 "123" 当 int 用)、数组越界访问这些运行时才暴露的问题。建议所有从 JSON 取值的地方都加 isXXX() 检查,哪怕多三行代码。








