跳到主要内容
nlohmann/json 详解:现代 C++ 的 JSON 处理方案 | 极客日志
C++
nlohmann/json 详解:现代 C++ 的 JSON 处理方案 介绍 nlohmann/json 库,涵盖安装、核心功能、进阶用法及典型场景。该库为单头文件 C++ JSON 库,支持强类型安全、跨平台及高性能操作。内容包括数据类型映射、对象操作、序列化反序列化、JSON 指针、自定义类型转换、错误处理及性能优化技巧。适用于配置文件解析、REST API 交互及数据持久化。
一、概述:为什么选择 nlohmann/json?
nlohmann/json 是由德国程序员 Niels Lohmann 开发的一个开源 C++ JSON 库,自 2013 年发布以来,因其极简的 API 设计 、零依赖的头文件库 特性,以及完整的现代 C++ 支持 ,迅速成为 C++ 社区中最受欢迎的 JSON 库(GitHub 星标超 38k)。相较于传统 JSON 库(如 JsonCpp),它具有以下革命性优势:
强类型安全 :提供 at() 安全访问、类型检查 API
跨平台 :支持 Windows/Linux/macOS 及嵌入式系统
高性能 :比 JsonCpp 快 2 倍以上(官方基准测试 )
直觉式语法 :操作 JSON 像写 JavaScript 一样自然
j["user" ]["name" ] = "Alice" ;
适用场景:配置文件解析、REST API 交互、数据序列化存储
慎用场景:GB 级 JSON 处理(推荐 simdjson )
二、安装指南
nlohmann/json 是单头文件库 (single-header),只需包含 json.hpp 即可使用。同时支持主流包管理器:
安装方式对比表
平台/工具 安装命令 项目集成方式 通用(手动) 下载 json.hpp #include <nlohmann/json.hpp>Linux (apt) sudo apt install nlohmann-json3-dev自动链接 Windows (vcpkg) vcpkg install nlohmann-jsontarget_link_libraries(... nlohmann-json)macOS (Homebrew) brew install nlohmann-json自动链接 CMake (通用) find_package(nlohmann_json REQUIRED)target_link_libraries(... nlohmann_json::nlohmann_json)
推荐使用 CMake 集成确保版本兼容性
三、核心功能详解
1. 数据类型映射(无缝转换) JSON 类型 C++ 类型 示例代码 objectstd::map/std::unordered_mapj = {{"key", "value"}};arraystd::vector/std::listj = {1, 2, 3};stringstd::stringj = "Hello";numberint/double/floatj = 3.14;booleanboolj = true;nullnullptrj = nullptr;
2. JSON 对象操作(创建/访问/修改)
json j = {
{"name" , "Alice" },
{"scores" , {95 , 88.5 , 100 }},
{"metadata" , {{"id" , "A001" }, {"valid" , true }}}
};
std::string name = j.value ("name" , "Unknown" );
int mathScore = j.at ("scores" ).at (0 );
j["scores" ][1 ] = 90.0 ;
j["metadata" ]["tags" ] = {"top" };
3. 序列化与反序列化
std::string jsonStr = j.dump (4 );
auto j2 = json::parse (R"( { "device": "Sensor01", "values": [23.4, 18.9] } )" );
std::ofstream file ("data.json" ) ;
file << j;
std::ifstream inFile ("data.json" ) ;
inFile >> j2;
四、进阶用法
1. 嵌套结构与 JSON 指针 json config = {
{"server" , {
{"ip" , "192.168.1.1" },
{"ports" , {8080 , 8000 }}
}}
};
std::string ip = config[json_pointer ("/server/ip" )];
int mainPort = config[json_pointer ("/server/ports/0" )];
if (config.contains ("server" ) && config["server" ].is_object ()){
config["server" ]["timeout" ] = 30 ;
}
2. 自定义类型转换(实战示例) struct Employee {
int id;
std::string name;
std::vector<std::string> skills;
};
void to_json (json& j, const Employee& e) {
j = json{{"emp_id" , e.id}, {"full_name" , e.name}, {"competencies" , e.skills}};
}
void from_json (const json& j, Employee& e) {
j.at ("emp_id" ).get_to (e.id);
j.at ("full_name" ).get_to (e.name);
j.at ("competencies" ).get_to (e.skills);
}
Employee bob {101 , "Bob" , {"C++" , "Linux" }};
json j_bob = bob;
Employee bob_copy = j_bob.get <Employee>();
3. 错误处理最佳实践 try {
json j = json::parse (invalidJson);
int value = j.at ("key" ).get <int >();
} catch (json::parse_error& e) {
std::cerr << "Parse error: " << e.what () << '\n' ;
} catch (json::out_of_range& e) {
std::cerr << "Key error: " << e.what () << '\n' ;
} catch (json::type_error& e) {
std::cerr << "Type error: " << e.what () << '\n' ;
}
4. 性能优化关键技巧
json::array_t largeArray;
largeArray.reserve (10000 );
j["big_data" ] = std::move (largeArray);
struct StatsCollector : nlohmann::json_sax<json> {
bool key (std::string& key) override {
keys.insert (key);
return true ;
}
std::set<std::string> keys;
};
StatsCollector handler;
json::sax_parse (bigJsonData, handler);
#define JSON_NOEXCEPTION
j.contains ("key" );
5. JSON Patch 动态修改
json doc = {
{"name" , "John" },
{"age" , 30 }
};
json patch = {
{"op" , "replace" , "path" , "/age" , "value" , 31 },
{"op" , "add" , "path" , "/city" , "value" , "London" }
};
json patched = doc.patch (patch);
五、典型应用场景
1. 配置文件解析 json config;
try {
std::ifstream configFile ("config.json" ) ;
configFile >> config;
} catch (...) {
config = {
{"port" , 8080 },
{"debug" , true }
};
}
const int port = config.value ("port" , 80 );
const bool debug = config.value ("debug" , false );
2. REST API 客户端
auto res = httplib::Client ("api.example.com" ).Get ("/users/123" );
if (res && res->status == 200 ) {
json user = json::parse (res->body);
auto email = user.value ("contact.email" , "[email protected] " );
auto lastLogin = user[json_pointer ("/activity/last_login" )];
}
3. 数据持久化存储 struct SensorReadings {
std::string id;
std::vector<float > values;
};
SensorReadings data = get_sensor_data ();
json archive = data;
std::ofstream outFile ("data_log.json" , std::ios::app) ;
outFile << archive.dump () << '\n' ;
std::ifstream in ("data_log.json" ) ;
std::string line;
while (std::getline (in, line)) {
auto j = json::parse (line);
SensorReadings restored = j.get <SensorReadings>();
}
六、结语 nlohmann/json 通过精心设计的 API 和对现代 C++ 特性的深度应用,彻底解决了 C++ 处理 JSON 数据的痛点。其仅头文件的特性使得集成成本几乎为零,而强大的功能集能满足从简单配置解析到复杂数据转换的各种需求。
主流 JSON 库对比 特性 nlohmann/json RapidJSON JsonCpp 头文件库 ✅ ✅ ❌ C++11 语法支持 ✅ ❌ ❌ 异常安全 ✅ ⚠️ ✅ 自定义类型转换 ✅ ❌ ⚠️ JSON Patch 支持 ✅ ❌ ❌ 二进制格式支持 ✅ (CBOR/MessagePack) ⚠️ ❌
相关免费在线工具 Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
HTML转Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
JSON 压缩 通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
JSON美化和格式化 将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online