首页 > 解决方案 > 有没有办法使用 QJsonObject 在整个 json 文件中找到一个键?

问题描述

json 层次结构中任何级别的键,我如何在不知道路径中确切键的情况下找到该键?

标签: c++qtqjsonobject

解决方案


通常,这可以通过递归函数(一个调用自身的函数)来解决。我们首先将文档的对象传递给它,然后检查对象的键。如果没有找到键,我们将对每个键的值应用相同的函数。如果传递了一个数组,我们应该遍历它。

QJsonValue findKey(const QString& key, const QJsonValue& value) {
    if (value.isObject()) {
        const QJsonObject obj = value.toObject();
        if (obj.contains(key))
            return obj.value(key);           // return 'early' if object contains key    

        for (const auto& value : obj) {
            QJsonValue recurse = findKey(key, value);  // call itself, forwarding a value        
            if (!recurse.isNull())
                return recurse;              // value found, return 'early'
        }
    } else if (value.isArray()) {
        for (const auto& value : value.toArray()) {
            QJsonValue recurse = findKey(key, value);
            if (!recurse.isNull())
                return recurse;
        }
    }

    return QJsonValue();          // base case: a null value
}

int main(int argc, char *argv[])
{
    QFile file(":/res/scratch.json");   // json stored in a qrc with /res/ prefix
    file.open(QIODevice::ReadOnly);

    if (!file.isOpen()) {
        qDebug() << "error: couldn't open scratch.json";
        return 0;
    }

    QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
    qDebug() << "value:" << findKey("treasure", doc.object());
}

JSON 文件和相关输出的示例:

划痕.json:

{
    "deck": [
        "first mate",
        "sailor",
        "john muir"
    ],
    "cabin": [
        {
            "name": "lamp"
        },
        {
            "name": "treasure chest",
            "items": {
                "diamonds": 3,
                "silver": 5,
                "gold": 10,
                "safebox": {
                    "treasure": "shiny"
                }
            }
        }
    ]
}

输出:

value: QJsonValue(string, "shiny")

推荐阅读