QJsonObject能否嵌套查找?

一 概述

QJsonObject 支持嵌套查找,但需要逐层访问,因为 Qt 的 JSON API 是强类型的,没有内置的路径查询语法(如 JavaScript 的 obj.a.b.c)。

二 基本嵌套查找方法

假设有以下 JSON 数据:

{

"user": {

"profile": {

"name": "张三",

"address": {

"city": "北京",

"street": "长安街"

}

},

"settings": {

"theme": "dark"

}

}

}

1 逐层访问(推荐)

#include <QJsonDocument>

#include <QJsonObject>

#include <QJsonValue>

QJsonObject obj = ...; // 从文件或字符串解析得到的JSON对象

// 安全地逐层访问

if (obj.contains("user")) {

QJsonObject userObj = obj["user"].toObject();

if (userObj.contains("profile")) {

QJsonObject profileObj = userObj["profile"].toObject();

if (profileObj.contains("name")) {

QString name = profileObj["name"].toString();

qDebug() << "用户名:" << name;

}

}

}

2 链式访问(需注意空值检查)

// 简化写法,但可能不安全

QString name = obj["user"].toObject()["profile"].toObject()["name"].toString();

// 如果中间任何一级不存在,会返回空字符串或默认值

三 安全的嵌套查找辅助函数

由于 Qt 没有内置路径查找,可以自己实现一个辅助函数。

1 使用点分隔路径

/**

* 通过点分隔路径查找嵌套值(仅支持字符串键)

* @param obj 根对象

* @param path 路径,如 "user.profile.name"

* @return 找到的值,找不到返回 QJsonValue::Undefined

*/

QJsonValue findValueByPath(const QJsonObject& obj, const QString& path) {

QStringList keys = path.split('.');

QJsonValue current = obj;

for (const QString& key : keys) {

if (current.isObject()) {

current = current.toObject().value(key);

} else if (current.isArray()) {

bool ok;

int index = key.toInt(&ok);

if (ok && index >= 0 && index < current.toArray().size()) {

current = current.toArray().at(index);

} else {

return QJsonValue::Undefined;

}

} else {

return QJsonValue::Undefined;

}

if (current.isUndefined()) {

return QJsonValue::Undefined;

}

}

return current;

}

// 使用示例

QJsonValue value = findValueByPath(obj, "user.profile.name");

if (!value.isUndefined()) {

qDebug() << "找到值:" << value.toString();

}

2 支持数组索引的路径

// 查找 "users.0.profile.email" 这样的路径

QJsonValue findNestedValue(const QJsonObject& root, const QString& path) {

QStringList parts = path.split('.');

QJsonValue current = root;

for (const QString& part : parts) {

if (current.isObject()) {

QJsonObject obj = current.toObject();

if (obj.contains(part)) {

current = obj[part];

} else {

return QJsonValue::Undefined;

}

} else if (current.isArray()) {

QJsonArray arr = current.toArray();

bool ok;

int index = part.toInt(&ok);

if (ok && index >= 0 && index < arr.size()) {

current = arr.at(index);

} else {

return QJsonValue::Undefined;

}

} else {

return QJsonValue::Undefined;

}

}

return current;

}

四 QJsonObject 查找方法对比

1 逐层访问

类型安全代码清晰 代码冗长,需要多次检查。

2 链式访问

代码简洁 不安全,中间缺失会静默失败。

3 辅助函数

可重用,支持路径语法 需要额外实现,性能略差。

五 实际应用示例

// 解析复杂的JSON配置

QJsonObject config = loadConfig();

// 使用辅助函数查找嵌套值

QJsonValue timeout = findNestedValue(config, "network.connection.timeout");

if (!timeout.isUndefined() && timeout.isDouble()) {

int timeoutMs = timeout.toInt();

// 使用超时设置

}

// 查找数组中的嵌套对象

QJsonValue user = findNestedValue(config, "users.0");

if (user.isObject()) {

QJsonObject userObj = user.toObject();

QString name = userObj["name"].toString();

}

// 设置嵌套值(需要特殊处理)

bool setNestedValue(QJsonObject& root, const QString& path, const QJsonValue& value) {

QStringList parts = path.split('.');

QJsonObject* current = &root;

// 遍历到倒数第二层

for (int i = 0; i < parts.size() - 1; ++i) {

QString key = parts[i];

if (!current->contains(key) || !(*current)[key].isObject()) {

(*current)[key] = QJsonObject(); // 自动创建中间对象

}

current = const_cast<QJsonObject*>(&(*current)[key].toObject());

}

// 设置最后一层

(*current)[parts.last()] = value;

return true;

}

六 注意事项

  1. 类型检查至关重要

// 错误的做法

QString name = obj["user"].toObject()["name"].toString(); // 可能崩溃

// 正确的做法

if (obj["user"].isObject()) {

QJsonObject user = obj["user"].toObject();

if (user["name"].isString()) {

QString name = user["name"].toString();

}

}

2 性能考虑

嵌套越深,查找成本越高。

频繁查找建议缓存中间结果。

大数据量时考虑使用 QJsonDocument 的二进制格式。

3 QML 中的嵌套查找

在 QML 中可以直接使用点语法:

// QML中可以直接使用

var city = jsonObject.user.profile.address.city;

七 总结

QJsonObject 确实支持嵌套查找,但:

1 没有内置的路径查询语法,需要逐层访问或自己实现辅助函数。

2 类型安全很重要,必须检查每一级的类型。

3 推荐使用逐层访问确保代码健壮性,或封装可重用的路径查找函数。

4 对于复杂的 JSON 操作,可以考虑使用第三方库(如 JsonCpp、nlohmann/json)或 Qt 6 中增强的 JSON 支持。

Qt 5 的 JSON API 设计偏保守,强调类型安全而非便利性,这是其与 JavaScript 等动态语言处理 JSON 的主要区别。

相关推荐
郝学胜-神的一滴6 小时前
Qt 高级开发 009: C++ Lambda 表达式
开发语言·c++·qt·软件构建
ZC跨境爬虫9 小时前
模块化烹饪小程序开发日记 Day7:(菜谱详情接口开发与JSON数据读取全流程)
前端·javascript·css·ui·微信小程序·json
小鱼仙官10 小时前
Windonws 视频存储,10s/不限时
开发语言·qt·音视频
cpp_learners11 小时前
QT 窗体遮罩
qt·遮罩
我在人间贩卖青春15 小时前
重学Qt——绘图
qt
人还是要有梦想的15 小时前
QT数据库乱码、QT qml import导入库报错、ui界面分层设计
开发语言·qt·ui
苕皮蓝牙土豆15 小时前
【Qt工业上位机实战】从零打造高性能串口监控终端
开发语言·qt
郝学胜-神的一滴15 小时前
Qt 高级开发014 :信号槽connect函数精讲
开发语言·c++·qt·开源软件·用户界面
Shadow(⊙o⊙)15 小时前
Qt-Lambda捕获使用+阶段性综合使用
开发语言·c++·qt·qt5
W.W.H.17 小时前
Qt 程序工作原理深度解析
qt·系统架构·多线程