c++如何解析JSON数组对象_c++ rapidjson库解析与DOM操作【方法】

关键在于避免崩溃:解析前检查 ParseResult 和 IsObject()/IsArray(),取值前用 HasMember() 和类型判断,遍历数组用 SizeType 并先校验 IsArray()。

用 RapidJSON 解析 JSON 数组和对象,关键不是“能不能”,而是“怎么避免崩溃”——ParseError、空指针访问、类型误判这三类问题占了 90% 的实际报错。

解析前必须检查 ParseResultIsObject()/IsArray()

RapidJSON 不会自动抛异常,所有解析结果都靠手动校验。跳过这步,operator[]GetArray() 极易触发段错误。

  • document.Parse(json_str.c_str()) 返回 bool,必须判断是否为 true
  • 即使解析成功,也要用 doc.IsObject()doc.IsArray() 明确顶层结构,不能默认是对象
  • 对任意字段取值前,先用 HasMember("key") 判断存在性,再用 ["key"].IsString() 等确认类型

遍历 JSON 数组:用 SizeType 而非 int,且必须检查 IsArray()

数组长度类型是 rapidjson::SizeType(通常是 unsigned),直接用 int i = 0; i 在 32 位平台可能隐式截断;更危险的是,没检查 arr.IsArray() 就调 arr.Size(),会返回 0 并掩盖类型错误。

if (doc["items"].IsArray()) {
    const rapidjson::Value& arr = doc["items"];
    for (rapidjson::SizeType i = 0; i < arr.Size(); ++i) {
        if (arr[i].IsObject() && arr[i].HasMember("id")) {
            int id = arr[i]["id"].GetInt();
            // ...
        }
    }
}

访问嵌套对象字段:链式调用前每层都要判空

doc["data"]["user"]["name"].GetString() 这种写法看着简洁,但中间任一层缺失或类型不符,就会 crash。RapidJSON 不支持安全链式访问(类似 JS 的 optional chaining)。

  • 正确做法:逐层判断 HasMember() + IsXXX()
  • 或封装一个辅助函数,如 SafeGetString(const Value& v, const char* key),内部做完整校验
  • 特别注意:字符串字段要用 GetString(),不是 GetStringLength() —— 后者只返回长度,不保证以 \0 结尾

Document 生命周期必须长于所有引用它的 Value&

这是最容易被忽略的内存陷阱:把 document["items"] 存成局部 const Value& arr,然后在函数返回后还去遍历 arr —— document 已析构,arr 成悬垂引用,行为未定义。

  • 所有 Value& 引用必须确保其源 Document 对象仍在作用域内
  • 若需跨函数传递数据,拷贝 ValueValue copy = doc["x"])或改用 GenericValue> 配合自定义 allocator
  • 不要试图用 std::move(document) 来“转移所有权”——Document 不可移动,移动后原对象处于无效状态

真正卡住人的从来不是语法,而是文档里没写的隐含约束:类型必须严判、引用必须守生命周期、数组索引必须用 SizeType。写完解析逻辑后,用一段含缺失字段、错类型、空数组的 JSON 多测几轮,比读十页 API 文档更管用。