最直接的方法是使用 nlohmann::json::parse() 解析 json 字符串,需配合 try-catch 处理非法输入,因其 header-only、语法简洁、支持 c++11 且无需编译依赖。

用 nlohmann/json 解析 JSON 字符串最直接
绝大多数 C++ 项目现在都用 nlohmann/json 库,它 header-only、语法简洁、支持 C++11 起,不用编译依赖。你只要下载一个 json.hpp 文件放进工程,#include 就能开始解析。
常见错误是直接拿 std::string 构造 json 对象却没检查是否合法:
std::string s = R"({"name":"Alice","age":30})";
try {
auto j = nlohmann::json::parse(s); // 必须 try-catch
std::cout ()
-
parse()不会自动抛异常——只有非法 JSON 才抛nlohmann::json::parse_error,但空字符串、nullptr字符串也会触发 - 如果确定输入安全(比如自己生成的),可用
nlohmann::json j = s;简写,但生产环境不建议绕过try/catch - 字段访问前最好用
j.contains("key")或j.is_object()做类型/存在性检查,否则j["missing"].get<int>()</int>会抛out_of_range
从 JSON 字符串提取整数、字符串、布尔值要注意类型匹配
nlohmann::json 是类型擦除设计,取值必须显式声明目标类型,不能靠隐式转换。常见坑是把 "123" 当成数字取,或把 123 当成字符串取。
示例:
std::string s = R"({"count":42,"active":true,"id":"abc123"})";
auto j = nlohmann::json::parse(s);
// ✅ 正确
int count = j["count"].get<int>(); // 42
bool active = j["active"].get<bool>(); // true
std::string id = j["id"].get<:string>(); // "abc123"
<p>// ❌ 错误(运行时报错:type must be number, but is string)
// int bad = j["id"].get<int>();</int></p>
<p>// ✅ 安全写法:先判断类型再取
if (j["count"].is_number_integer()) {
int n = j["count"].get<int>();
}</int></p></:string></bool></int>
-
.get<t>()</t>要求 JSON 值类型与T严格匹配:JSONnumber→int/double;string→std::string;true/false→bool - JSON 中的数字默认是
double,即使写的是42。想确保整数用is_number_integer()判断,或用get<int64_t>()</int64_t>配合检查溢出 - 字符串字段若可能为
null,要用j.value("key", "default")提供 fallback,而不是直接j["key"]
解析嵌套对象和数组时别漏掉边界检查
JSON 里嵌套太常见了,比如 {"user":{"profile":{"email":"a@b.com"}}} 或 {"items":[1,2,3]}。直接链式访问 j["user"]["profile"]["email"] 看似方便,但任意一层缺失都会抛异常。
更稳妥的做法是逐层判空:
auto j = nlohmann::json::parse(json_str);
if (j.is_object() &&
j.contains("user") && j["user"].is_object() &&
j["user"].contains("profile") && j["user"]["profile"].is_object() &&
j["user"]["profile"].contains("email")) {
std::string email = j["user"]["profile"]["email"].get<:string>();
}</:string>
- 也可以用
j.value("user", nlohmann::json::object()).value("profile", nlohmann::json::object()).value("email", ""),但可读性差,且无法区分“字段不存在”和“字段值为null” - 遍历数组时,用
for (const auto& item : j["items"])即可,但得先确认j["items"].is_array(),否则迭代器行为未定义 - 数组索引越界不会自动 throw,
j["items"][100]返回一个空的json对象(is_null() == true),需手动检查
不用第三方库时,std::regex 或 rapidjson 的取舍
如果项目禁止引入外部头文件(比如某些嵌入式或军工场景),std::regex 解析 JSON 是典型反模式:JSON 语法递归嵌套,正则无法可靠处理引号转义、嵌套对象/数组等,极易漏匹配或崩溃。
真正可行的轻量替代是 rapidjson,它比 nlohmann 更底层,但体积小、性能高、无 STL 依赖(可禁用 std::string):
-
rapidjson默认用 SAX 模式流式解析,内存占用低;DOM 模式类似nlohmann,用Document加载整个 JSON - 错误处理靠返回码:
ParseResult ok = doc.Parse(json_str.c_str()); if (!ok) { ... },错误位置在doc.GetErrorOffset() - 取值方式更啰嗦:
doc["name"].GetString()要求字段存在且类型匹配,否则 crash;必须配合HasMember()和IsString()一起用
除非有硬性约束,否则没必要为省几百 KB 头文件去换 rapidjson —— nlohmann/json 编译后体积影响极小,调试体验和安全性远胜手写解析逻辑。
最易被忽略的是编码:所有解析库默认按 UTF-8 处理,如果输入字符串实际是 GBK 或 UTF-16,必须先转码,否则 parse() 会失败或乱码。别指望库自动检测编码。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










