选nlohmann/json因其头文件即用、无依赖、语法现代、错误提示清晰;支持operator[]、==、结构化绑定,兼容string_view和移动语义;仅需包含json.hpp即可解析与序列化json。

为什么选 nlohmann/json 而不是其他库
因为它的头文件即用、无依赖、语法接近现代 C++,且错误提示清晰。相比 jsoncpp(需编译、API 陈旧)或 rapidjson(模板繁杂、手动管理内存),nlohmann/json 的 json 类型像内置类型一样自然:支持直接用 operator[]、operator==、结构化绑定,也兼容 std::string_view 和移动语义。
快速上手:读取和写入 JSON 字符串
只需一个头文件,不需链接任何库。下载 json.hpp 放入项目目录后,直接 #include "json.hpp" 即可使用。
#include "json.hpp"
#include <iostream>
#include <string>
using json = nlohmann::json;
int main() {
// 解析字符串
std::string s = R"({"name":"Alice","age":30,"hobbies":["coding","reading"]})";
json j = json::parse(s);
// 访问字段(自动类型检查)
std::string name = j["name"]; // 自动转 string
int age = j["age"]; // 自动转 int
std::vector<std::string> hobbies = j["hobbies"]; // 自动转 vector
// 序列化回字符串
std::string output = j.dump(2); // 缩进 2 空格
std::cout << output << "\n";
}
- 用
R"(...)"原始字符串字面量避免转义麻烦 -
j["missing_key"]默认返回json::value_t::null,访问前建议用j.contains("key")或j.is_null()判断 -
dump()默认不缩进;传整数参数控制缩进空格数
常见坑:类型不匹配与异常处理
解析成功不等于字段可用——JSON 中的 "123" 是字符串,不是数字;null 值会静默转成默认构造值,容易掩盖逻辑错误。
- 强制类型转换失败会抛
nlohmann::json::type_error,例如j["age"].get<int>()</int>对"thirty"失败 - 推荐用
get<t>()</t>+ 异常捕获,或更安全的get_ptr<t>()</t>(返回nullptr表示失败) - 对不确定结构的数据,先用
j.is_object()/j.is_array()/j.is_string()检查类型
try {
int x = j["count"].get<int>(); // 可能 throw
} catch (const nlohmann::json::exception& e) {
std::cerr << "JSON error: " << e.what() << "\n";
}
进阶用法:自定义类型序列化
让自己的结构体支持 JSON 自动读写,只需定义 to_json 和 from_json 两个非成员函数,放在类所在命名空间内即可。
立即学习“C++免费学习笔记(深入)”;
struct Person {
std::string name;
int age;
};
void to_json(json& j, const Person& p) {
j = json{{"name", p.name}, {"age", p.age}};
}
void from_json(const json& j, Person& p) {
j.at("name").get_to(p.name);
j.at("age").get_to(p.age);
}
// 使用:
Person p{"Bob", 25};
json j = p; // 自动调用 to_json
Person p2 = j.get<Person>(); // 自动调用 from_json
注意:j.at("key") 抛异常(比 j["key"] 更严格),适合必须存在的字段;get_to() 是就地赋值,避免临时对象构造开销。
嵌套结构、std::optional、容器类型都可同样处理,但要注意循环引用会导致无限递归 —— nlohmann/json 不做运行时环检测,得靠设计规避。











