nlohmann/json 是 C++ 中最流行的 JSON 处理库之一,以其简洁的 API、高性能和易用性著称。以下是详细的使用指南,涵盖从基础到进阶的操作。
![图片[1]_C++ 使用 nlohmann/json 库解析和处理 JSON 数据的操作指南_知途无界](https://zhituwujie.com/wp-content/uploads/2025/10/d2b5ca33bd20251029093140.png)
一、安装与引入
1. 安装方式
- 直接包含头文件(推荐):
该库仅有一个头文件json.hpp,下载后放入项目目录即可。# 从 GitHub 下载最新版(如 v3.11.2) wget https://github.com/nlohmann/json/releases/download/v3.11.2/json.hpp - 包管理器安装(如 vcpkg/conan):
# vcpkg vcpkg install nlohmann-json # conan conan install nlohmann_json/3.11.2
2. 引入库
在代码中包含头文件:
#include <nlohmann/json.hpp>
using json = nlohmann::json; // 别名简化书写
二、基础操作
1. JSON 数据的创建
从字面量构造
// 空对象/数组
json j_obj{}; // {} (空对象)
json j_arr{}; // [] (空数组)
// 手动构造对象(键值对)
json person;
person["name"] = "Alice";
person["age"] = 25;
person["is_student"] = false;
// 直接初始化(推荐)
json j = {
{"name", "Bob"},
{"age", 30},
{"hobbies", {"reading", "coding"}} // 嵌套数组
};
从字符串解析
std::string json_str = R"({"name":"Charlie","score":95.5})";
json j = json::parse(json_str); // 解析字符串
// 从文件读取
std::ifstream file("data.json");
json j_file = json::parse(file); // 解析文件内容
2. 访问 JSON 数据
对象访问
json j = {{"name", "Alice"}, {"age", 25}};
// 方式1:[] 操作符(不检查键是否存在)
std::string name = j["name"]; // "Alice"
int age = j["age"]; // 25
// 方式2:.at() 方法(检查键是否存在,异常安全)
try {
std::string name = j.at("name"); // 安全访问
int invalid = j.at("invalid_key"); // 抛出 json::out_of_range 异常
} catch (const json::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
// 检查键是否存在
if (j.contains("name")) {
std::cout << "Name exists: " << j["name"] << std::endl;
}
数组访问
json arr = {"a", "b", 123};
std::string first = arr[0]; // "a" (索引从0开始)
int num = arr[2]; // 123
3. 修改 JSON 数据
json j = {{"name", "Alice"}, {"age", 25}};
// 修改值
j["age"] = 26; // 更新 age
j["city"] = "New York"; // 新增键值对
// 修改数组
json arr = {1, 2, 3};
arr[1] = 99; // arr 变为 [1, 99, 3]
arr.push_back(4); // arr 变为 [1, 99, 3, 4]
三、类型转换
1. JSON 与 C++ 类型互转
JSON → C++
json j = {
{"name", "Bob"},
{"age", 30},
{"is_student", true},
{"scores", {90, 85, 95}},
{"metadata", nullptr}
};
std::string name = j["name"]; // string
int age = j["age"]; // int
bool is_student = j["is_student"]; // bool
std::vector<int> scores = j["scores"]; // vector<int>
double score = j["scores"][0]; // double (隐式转换)
std::nullptr_t meta = j["metadata"]; // nullptr_t (或直接判断是否为 null)
C++ → JSON
json j;
j["name"] = std::string("Alice"); // string
j["age"] = 25; // int
j["pi"] = 3.14159; // double
j["is_valid"] = true; // bool
j["tags"] = {"cpp", "json", "nlohmann"}; // vector<string>
j["empty"] = nullptr; // null
2. 特殊类型处理
- 嵌套对象/数组:自动递归转换。
json nested = { {"user", {{"name", "Tom"}, {"age", 40}}}, {"ids", {1, 2, 3}} }; std::string user_name = nested["user"]["name"]; // "Tom" - 自定义类型:需手动实现序列化(见进阶部分)。
四、进阶操作
1. 遍历 JSON 数据
遍历对象
json j = {{"name", "Alice"}, {"age", 25}, {"city", "Beijing"}};
for (auto& [key, value] : j.items()) { // C++17 结构化绑定
std::cout << key << ": " << value << std::endl;
}
// 输出:
// name: "Alice"
// age: 25
// city: "Beijing"
遍历数组
json arr = {"a", "b", "c"};
for (const auto& item : arr) {
std::cout << item << std::endl; // 依次输出 a, b, c
}
2. 合并与合并 JSON
json j1 = {{"name", "Alice"}, {"age", 25}};
json j2 = {{"city", "Beijing"}, {"hobbies", {"reading"}}};
// 合并 j2 到 j1(j1 被修改)
j1.update(j2);
// j1 现在为 {"name":"Alice","age":25,"city":"Beijing","hobbies":["reading"]}
3. 序列化为字符串/文件
json j = {{"name", "Bob"}, {"age", 30}};
// 转为字符串
std::string json_str = j.dump(); // 无格式(紧凑)
std::string pretty_str = j.dump(4); // 缩进4空格(美化)
// 写入文件
std::ofstream out("output.json");
out << pretty_str; // 写入美化后的 JSON
五、错误处理
1. 解析错误
try {
json j = json::parse("{invalid_json}"); // 非法格式
} catch (const json::parse_error& e) {
std::cerr << "Parse error: " << e.what()
<< " (offset: " << e.byte << ")" << std::endl;
}
2. 访问错误
json j = {{"name", "Alice"}};
try {
int age = j.at("age"); // 键不存在
} catch (const json::out_of_range& e) {
std::cerr << "Key not found: " << e.what() << std::endl;
}
六、完整示例
#include <iostream>
#include <nlohmann/json.hpp>
#include <fstream>
#include <vector>
using json = nlohmann::json;
int main() {
// 1. 创建 JSON
json person = {
{"name", "Alice"},
{"age", 25},
{"hobbies", {"reading", "coding"}},
{"address", {
{"city", "Beijing"},
{"zip", "100000"}
}}
};
// 2. 序列化为字符串
std::string json_str = person.dump(2); // 缩进2空格
std::cout << "Serialized JSON:\n" << json_str << std::endl;
// 3. 写入文件
std::ofstream file("person.json");
file << person.dump(4); // 美化输出
file.close();
// 4. 从文件读取并解析
std::ifstream in("person.json");
json loaded_person = json::parse(in);
std::cout << "Loaded name: " << loaded_person["name"] << std::endl;
// 5. 遍历嵌套对象
for (auto& [key, value] : loaded_person["address"].items()) {
std::cout << key << ": " << value << std::endl;
}
return 0;
}
七、注意事项
- 性能:
nlohmann/json在解析和生成时性能较高,但对超大型 JSON 文件(GB 级别)建议使用流式解析(如json::parse(sax)接口)。 - 线程安全:单个
json对象非线程安全,多线程操作需加锁。 - 自定义类型:若需序列化自定义类,需实现
to_json(json&, const T&)和from_json(const json&, T&)函数(详见官方文档)。
通过本指南,你可以快速掌握 nlohmann/json 的核心功能,高效处理 JSON 数据!
© 版权声明
文中内容均来源于公开资料,受限于信息的时效性和复杂性,可能存在误差或遗漏。我们已尽力确保内容的准确性,但对于因信息变更或错误导致的任何后果,本站不承担任何责任。如需引用本文内容,请注明出处并尊重原作者的版权。
THE END

























暂无评论内容