最简单可靠的方式是将 single_include/nlohmann/json.hpp 复制到项目 include/ 目录并 #include ,确保 C++11+ 标准;安全读取需先 contains() 再 is_type() 或用 value() 设默认值;UTF-8 乱码需检查文件编码、读取模式及控制台代码页。
直接把 nlohmann/json.hpp 头文件放进工程目录是最简单、最可靠的方式,不需要编译安装,也不依赖 CMake 的 find_package 或第三方包管理器(除非你用 vcpkg/conan 管理整个依赖链)。
常见错误是只下载了 GitHub 仓库 zip 却没把 include/nlohmann 目录下的头文件正确放到 include 路径里,导致编译报错:fatal error: nlohmann/json.hpp: No such file or directory。
single_include/nlohmann/json.hpp,复制到你项目的 include/ 下,然后在源码中写 #include
-std=c++11 或以上),否则会报 error: ‘using’ declaration cannot be used in a template 类似错误include_directories(${CMAKE_SOURCE_DIR}/include),不要尝试 link 任何库 —— 它是纯头文件库nlohmann/json 默认使用“宽松访问”(即 operator[]),对不存在的字段返回一个空对象,但如果你调用 .get 或 .at("key") 就可能抛出 nlohmann::json::out_of_range 异常。生产环境不建议裸用 .at() 或强制类型转换。
安全读取字段的核心原则:先检查键是否存在 + 再检查类型是否匹配。
json_obj.contains("field") 判断字段是否存在(比 json_obj.count("field") > 0 更直观)json_obj["field"].is_number_in
teger()、.is_string()、.is_null() 显式校验类型json_obj.value("field", default_value) 获取带默认值的字段,比如 json_obj.value("timeout", 30),它不会抛异常,也无需提前判断存在性json_obj["data"]["items"][0]["id"] 前先拆成多步,并每步检查,例如:if (j.contains("data") && j["data"].contains("items") && !j["data"]["items"].empty()) { ... }数组和对象在 nlohmann/json 中统一为 json 类型,但遍历方式不同。别直接用 for (auto& x : j) 处理混合结构,容易误判类型。
典型场景:读取 {"users": [{"name": "Alice", "age": 25}, {"name": "Bob", "age": 30}]}
if (j.contains("users") && j["users"].is_array())
for (const auto& user : j["users"]) {
if (!user.is_object()) continue;
std::string name = user.value("name", "unknown");
int age = user.value("age", 0);
// ...
}for (const auto& [key, value] : obj.items()),注意 C++17 才支持结构化绑定;若用旧标准,改用 for (auto it = obj.begin(); it != obj.end(); ++it)
j["users"][999] 会返回空值,后续调用 .get() 会抛异常 —— 所以务必先 .size() 判断nlohmann/json 本身完全支持 UTF-8,但乱码通常来自外部输入源未按 UTF-8 编码,或 Windows 控制台未正确设置代码页。
parse error at line 1, column 1: syntax error while parsing value - invalid string: ill-formed UTF-8 byte
std::ifstream f("data.json", std::ios::binary);
f.seekg(0, std::ios::end);
size_t size = f.tellg();
f.seekg(0);
std::string content(size, '\0');
f.read(&content[0], size); // 避免文本模式换行符截断
nlohmann::json j = nlohmann::json::parse(content);Content-Type: application/json; charset=utf-8,且响应体确实是 UTF-8 编码SetConsoleOutputCP(CP_UTF8);(Windows API),或改用 wprintf + std::wstring_convert(已弃用,慎用)实际项目中最容易被忽略的是:JSON 输入不可信,所有字段访问都应视为潜在失败点。宁可多写两行 contains() 和 is_xxx(),也不要依赖文档“保证有这个字段”。