qt解析json核心是主动防御:qjsondocument::fromjson()后须先判isnull()和isarray()/isobject(),嵌套取值需逐层校验contains()与类型,qjsonarray遍历时每个qjsonvalue都必须isxxx()判断。

Qt 解析 JSON 数据包,核心是别信“自动成功”——QJsonDocument::fromJson() 不报错不等于数据结构合法,QJsonObject::value() 返回空 QJsonValue 也不抛异常,所有中间层缺失或类型错配都会静默失效,最终导致取值为空或崩溃。
QJsonDocument::fromJson() 后必须校验 isNull() 和 isArray()/isObject()
很多人直接 QJsonDocument doc = QJsonDocument::fromJson(data); auto obj = doc.object(); 就开始用,但一旦原始 JSON 是数组(如 [{"id":1}])或解析失败(如含非法字符),doc.object() 会返回空对象,后续所有访问都无效。
- 先检查
!doc.isNull(),否则说明解析失败(比如 UTF-8 BOM 缺失、控制字符混入) - 再根据预期结构调用
doc.isArray()或doc.isObject(),而不是无脑.object() - 若 JSON 是顶层数组,必须用
doc.array(),而非.object()—— 这是新手最常卡住的点
嵌套取值时不能链式调用 root["a"]["b"]["c"].toString()
这种写法在任意一层键不存在、或值类型不是对象/数组时,会返回空 QJsonValue,再继续调用 toString() 得到空字符串,但你根本不知道哪一层断了。
- 必须逐层判断:
root.contains("data") && root["data"].isObject() - 再取子对象:
QJsonObject dataObj = root["data"].toObject() - 再查下一层:
dataObj.contains("items") && dataObj["items"].isArray() - 最后才安全获取:
QJsonArray items = dataObj["items"].toArray()
遍历 QJsonArray 时每个元素都要 isObject()/isString() 校验
QJsonArray 里每个元素都是 QJsonValue,它可能是对象、字符串、数字、null,甚至另一个数组。直接 array[i].toObject() 或 array.at(i).toString() 是高危操作。
- 用
array.size()获取长度,别依赖at(i)的边界检查(它不检查越界) - 对每个
QJsonValue val,先if (val.isObject()) { ... }或if (val.isString()) { ... } - 避免
array[i]写法——i 越界时行为未定义,且无类型提示 - 特别注意:接口文档说“字段是 number”,实际可能返回字符串(如
"123"),isDouble()会返回false,但toString()可能意外成功
真正难的不是语法,而是把“每一步都可能为空或类型不符”当成默认前提;Qt 的 JSON API 设计就是偏向静默失败,靠开发者主动防御,漏掉一次 contains() 或 isObject() 就可能让程序在某个边缘请求下静默丢数据。











