c++如何解析json数据_c++ nlohmann/json库引入与字段读取【实战】

最简单可靠的方式是将 single_include/nlohmann/json.hpp 复制到项目 include/ 目录并 #include ,确保 C++11+ 标准;安全读取需先 contains() 再 is_type() 或用 value() 设默认值;UTF-8 乱码需检查文件编码、读取模式及控制台代码页。

如何在 C++ 项目中正确引入 nlohmann/json 库

直接把 nlohmann/json.hpp 头文件放进工程目录是最简单、最可靠的方式,不需要编译安装,也不依赖 CMake 的 find_package 或第三方包管理器(除非你用 vcpkg/conan 管理整个依赖链)。

常见错误是只下载了 GitHub 仓库 zip 却没把 include/nlohmann 目录下的头文件正确放到 include 路径里,导致编译报错:fatal error: nlohmann/json.hpp: No such file or directory

  • 推荐做法:从 nlohmann/json 发布页 下载最新 single_include/nlohmann/json.hpp,复制到你项目的 include/ 下,然后在源码中写 #include
  • 确保编译器支持 C++11 或更高(-std=c++11 或以上),否则会报 error: ‘using’ declaration cannot be used in a template 类似错误
  • 如果用 CMake,只需加一句 include_directories(${CMAKE_SOURCE_DIR}/include),不要尝试 link 任何库 —— 它是纯头文件库

读取 JSON 字段时怎么避免运行时崩溃

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_integer().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()) { ... }

解析 JSON 数组和对象的实际写法

数组和对象在 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)
  • 数组索引越界不会自动 throw,但 j["users"][999] 会返回空值,后续调用 .get() 会抛异常 —— 所以务必先 .size() 判断

中文字符串乱码或解析失败怎么办

nlohmann/json 本身完全支持 UTF-8,但乱码通常来自外部输入源未按 UTF-8 编码,或 Windows 控制台未正确设置代码页。

  • 确保 JSON 文件保存为 UTF-8 无 BOM 格式(VS Code / Notepad++ 都可设),BOM 会导致 parse error at line 1, column 1: syntax error while parsing value - invalid string: ill-formed UTF-8 byte
  • 从文件读取时,用二进制模式打开(尤其 Windows):
    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);
  • 如果 JSON 来自网络响应,确认 HTTP header 中 Content-Type: application/json; charset=utf-8,且响应体确实是 UTF-8 编码
  • 控制台输出中文乱码?Linux/macOS 一般没问题;Windows 建议在程序开头加 SetConsoleOutputCP(CP_UTF8);(Windows API),或改用 wprintf + std::wstring_convert(已弃用,慎用)

实际项目中最容易被忽略的是:JSON 输入不可信,所有字段访问都应视为潜在失败点。宁可多写两行 contains()is_xxx(),也不要依赖文档“保证有这个字段”。