最常用方式是用std::ifstream直接传给nlohmann::json::parse(),v5.3.0+自动跳过utf-8 bom;访问嵌套字段应优先用.value("key", default)避免崩溃;大文件需考虑流式解析器如simdjson;中文乱码主因是文件或源码编码不统一,须全用utf-8无bom。

用 nlohmann/json 直接读取文件到 json 对象
最常用、最省事的方式就是用 nlohmann::json 库配合 std::ifstream,它原生支持从流解析 JSON。只要文件编码是 UTF-8(无 BOM),基本不会出错。
常见错误现象:json::parse_error 异常,通常是因为文件为空、路径错、含不可见控制字符(比如 Windows 记事本保存的 UTF-8+BOM)、或 JSON 格式本身不合法(漏逗号、多逗号、单引号代替双引号)。
- 确保文件路径正确,建议用绝对路径或检查
std::ifstream的.is_open()返回值 - 不要手动读成 string 再 parse——除非你要预处理(如删注释),否则直接传流更安全
- 如果文件带 BOM,
nlohmann/json5.3.0+ 版本能自动跳过,但低版本会报[json.exception.parse_error.101]
std::ifstream f("config.json");
if (!f.is_open()) {
throw std::runtime_error("cannot open config.json");
}
nlohmann::json j = nlohmann::json::parse(f); // 自动处理 UTF-8 BOM(v5.3.0+)
访问嵌套字段时怎么避免崩溃
JSON 字段缺失是常态,直接用 ["key"] 下标访问会触发断言或抛异常(out_of_range)。必须用安全访问方式。
使用场景:配置文件里某些字段是可选的,比如 "timeout" 可能不存在,但代码里又想给个默认值。
- 用
.value("key", default_value):类型必须匹配,且只适用于基础类型(int、std::string等) - 用
.at("key"):显式抛异常,适合“该字段必须存在”的逻辑分支 - 用
.find("key") != j.end()判断是否存在,再取值;适合需要复杂默认逻辑的场景
int timeout = j.value("timeout", 30); // 安全,默认 30
std::string host = j.value("server.host", "localhost"); // 支持点号路径(v3.11.2+)
auto port_it = j.find("port");
int port = port_it != j.end() ? port_it->get<int>() : 8080;
</int>
解析大 JSON 文件时内存暴涨怎么办
nlohmann/json 是 DOM 解析器,整个 JSON 必须加载进内存。一个 100MB 的 JSON 文件,解析后可能占用 300MB+ 内存,尤其含大量字符串时。
性能影响:不仅吃内存,还拖慢启动——解析时间随文件大小近似线性增长。
- 确认是否真需要全量加载:如果只是查几个字段,考虑用流式解析器(如
simdjson或rapidjson的 SAX 模式) - 用
nlohmann/json时,可提前调用j.clear()释放不用的子树 - 避免反复解析同一文件:缓存
nlohmann::json对象,别每次读都 parse
注意:simdjson 要求输入内存连续且只读,不能像 std::ifstream 那样边读边解析;若文件超大又不能全载入,得自己 mmap + simdjson::dom::parser。
中文字段名或字符串乱码的根源在哪
不是库的问题,而是文件保存格式和 C++ 运行环境的组合问题。Windows 上用记事本保存为 UTF-8,实际加了 BOM;而 VS 默认源码编码是 GBK,std::string 字面量若含中文,编译后就是 GBK 编码字节——和 JSON 里的 UTF-8 中文混在一起就崩。
- 统一用 UTF-8 无 BOM 保存 JSON 文件(推荐 VS Code 或 Notepad++)
- C++ 源码也存为 UTF-8 无 BOM,并在文件头加
#pragma execution_character_set("utf-8")(MSVC)或用u8"中文"前缀字面量 - 打印调试时,别用
std::cout 直接输出中文——终端编码可能不匹配,改用日志写文件再查看
最容易被忽略的是:即使 JSON 解析成功,j["中文键"].get<:string>()</:string> 返回的仍是 UTF-8 编码的 std::string,后续若要 WinAPI 调用(如 CreateFileA),得先转 GBK 或用宽字符接口。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










