复杂的QVariant写入文件以及从文件中读入复原

将复杂的QVariant写入Json文件

要将复杂的 QVariant(包含 QListQMap 等)写入 JSON 文件,你可以借助 Qt 的 QJsonDocumentQJsonObjectQJsonArrayQVariant 转换为 JSON 格式。以下是实现代码:


实现代码:

cpp 复制代码
#include <QVariant>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>

// 辅助函数:递归将 QVariant 转换为 QJsonValue
QJsonValue variantToJsonValue(const QVariant &variant) {
    switch (variant.type()) {
        case QVariant::Map: {
            QJsonObject jsonObj;
            QMap<QString, QVariant> map = variant.toMap();
            for (auto it = map.begin(); it != map.end(); ++it) {
                jsonObj.insert(it.key(), variantToJsonValue(it.value()));
            }
            return jsonObj;
        }
        case QVariant::List: {
            QJsonArray jsonArray;
            QList<QVariant> list = variant.toList();
            for (const QVariant &item : list) {
                jsonArray.append(variantToJsonValue(item));
            }
            return jsonArray;
        }
        case QVariant::String:
            return QJsonValue(variant.toString());
        case QVariant::Int:
            return QJsonValue(variant.toInt());
        case QVariant::Double:
            return QJsonValue(variant.toDouble());
        case QVariant::Bool:
            return QJsonValue(variant.toBool());
        default:
            // 对于其他类型,尝试将其转换为字符串
            if (variant.canConvert<QString>()) {
                return QJsonValue(variant.toString());
            } else {
                return QJsonValue(); // 空值
            }
    }
}

// 写入 QVariant 到 JSON 文件
void writeVariantToJsonFile(const QVariant &variant, const QString &filePath) {
    // 将 QVariant 转换为 QJsonValue
    QJsonValue jsonValue = variantToJsonValue(variant);

    // 判断是否是对象或数组,否则包装成对象
    QJsonDocument jsonDoc;
    if (jsonValue.isObject()) {
        jsonDoc = QJsonDocument(jsonValue.toObject());
    } else if (jsonValue.isArray()) {
        jsonDoc = QJsonDocument(jsonValue.toArray());
    } else {
        QJsonObject wrapper;
        wrapper.insert("value", jsonValue);
        jsonDoc = QJsonDocument(wrapper);
    }

    // 将 JSON 写入文件
    QFile file(filePath);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        qWarning() << "无法打开文件:" << filePath;
        return;
    }

    file.write(jsonDoc.toJson(QJsonDocument::Indented)); // 格式化输出
    file.close();
}

// 示例主函数
int main() {
    // 构造一个复杂的 QVariant 数据结构
    QVariantMap map;
    map["key1"] = "value1";
    map["key2"] = 42;
    map["key3"] = QVariantList{"item1", "item2", 123, QVariantMap{{"nestedKey", "nestedValue"}}};
    map["key4"] = QVariantMap{{"subKey1", "subValue1"}, {"subKey2", 99}};
    map["key5"] = true;

    QVariant complexVariant = map;

    // 写入文件
    QString filePath = "output.json";
    writeVariantToJsonFile(complexVariant, filePath);

    qDebug() << "复杂 QVariant 已写入 JSON 文件:" << filePath;
    return 0;
}

说明:

  1. 核心方法:variantToJsonValue

    • 这是一个递归函数,将 QVariant 转换为 QJsonValue
    • 支持以下类型:
      • QVariant::Map -> 转换为 QJsonObject
      • QVariant::List -> 转换为 QJsonArray
      • 基本类型(QStringintdoublebool) -> 转换为对应的 JSON 值
      • 对于其他类型,尝试调用 toString() 进行转换,如果不支持则写入空值。
  2. JSON 文件写入:writeVariantToJsonFile

    • 使用 QJsonDocumentQJsonValue 写入 JSON 文件。
    • 自动判断数据结构是 JSON 对象还是数组,如果是其他类型,则将其包装为一个 JSON 对象。
    • 通过 QJsonDocument::Indented 格式化输出,生成可读性更高的 JSON 文件。
  3. 支持的类型

    • QVariantMap -> JSON 对象
    • QVariantList -> JSON 数组
    • 基本类型(QStringintdoublebool 等)
  4. 输出示例

    假设输入的 QVariant 是如下结构:

    cpp 复制代码
    QVariantMap map;
    map["key1"] = "value1";
    map["key2"] = 42;
    map["key3"] = QVariantList{"item1", "item2", 123, QVariantMap{{"nestedKey", "nestedValue"}}};
    map["key4"] = QVariantMap{{"subKey1", "subValue1"}, {"subKey2", 99}};
    map["key5"] = true;

    输出的 output.json 文件内容为:

    json 复制代码
    {
        "key1": "value1",
        "key2": 42,
        "key3": [
            "item1",
            "item2",
            123,
            {
                "nestedKey": "nestedValue"
            }
        ],
        "key4": {
            "subKey1": "subValue1",
            "subKey2": 99
        },
        "key5": true
    }
  5. 注意事项

    • 如果文件路径无效或者没有写入权限,会发出警告。
    • QVariant 中包含无法识别的类型时,将尝试将其转换为字符串,否则写入空值。

使用方法:

将上述代码复制并运行,程序会将复杂的 QVariant 数据结构写入 output.json 文件,你可以用任意文本编辑器或 JSON 查看器打开文件查看结果。

从Json文件中复原QVariant

要将刚才写入的 JSON 文件重新读入到程序中,并解析为一个 QVariant 数据结构,可以使用 Qt 的 QJsonDocumentQJsonObject/QJsonArray 类。以下是实现代码:


实现代码:

cpp 复制代码
#include <QVariant>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>

// 辅助函数:递归将 QJsonValue 转换为 QVariant
QVariant jsonValueToVariant(const QJsonValue &jsonValue) {
    if (jsonValue.isObject()) {
        QVariantMap map;
        QJsonObject obj = jsonValue.toObject();
        for (auto it = obj.begin(); it != obj.end(); ++it) {
            map.insert(it.key(), jsonValueToVariant(it.value()));
        }
        return map;
    } else if (jsonValue.isArray()) {
        QVariantList list;
        QJsonArray array = jsonValue.toArray();
        for (const QJsonValue &item : array) {
            list.append(jsonValueToVariant(item));
        }
        return list;
    } else if (jsonValue.isString()) {
        return jsonValue.toString();
    } else if (jsonValue.isDouble()) {
        return jsonValue.toDouble();
    } else if (jsonValue.isBool()) {
        return jsonValue.toBool();
    } else if (jsonValue.isNull()) {
        return QVariant(); // 空值
    }
    return QVariant();
}

// 从 JSON 文件中读取内容并转换为 QVariant
QVariant readJsonFileToVariant(const QString &filePath) {
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning() << "无法打开文件:" << filePath;
        return QVariant();
    }

    QByteArray jsonData = file.readAll();
    file.close();

    QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData);
    if (jsonDoc.isNull()) {
        qWarning() << "JSON 文件格式错误:" << filePath;
        return QVariant();
    }

    // 根据 JSON 类型返回 QVariant
    if (jsonDoc.isObject()) {
        return jsonValueToVariant(jsonDoc.object());
    } else if (jsonDoc.isArray()) {
        return jsonValueToVariant(jsonDoc.array());
    }

    return QVariant(); // 不支持的 JSON 格式
}

// 示例主函数
int main() {
    // 写入 JSON 文件路径
    QString filePath = "output.json";

    // 从 JSON 文件中读取并解析为 QVariant
    QVariant variant = readJsonFileToVariant(filePath);

    // 打印解析结果
    qDebug() << "从 JSON 文件解析出的 QVariant 数据:";
    qDebug() << variant;

    // 如果需要递归打印,可以使用 QVariant 的转字符串函数(如前所述的 variantToString)

    return 0;
}

说明:

  1. 核心方法:jsonValueToVariant

    • 递归地将 QJsonValue 转换为 QVariant
    • 支持以下类型:
      • QJsonObject -> 转换为 QVariantMap
      • QJsonArray -> 转换为 QVariantList
      • 基本类型(字符串、数字、布尔值等) -> 转换为对应的 QVariant 类型
      • 空值(null) -> 转换为默认的 QVariant()
  2. 从 JSON 文件读取:readJsonFileToVariant

    • 读取 JSON 文件内容到内存。
    • 使用 QJsonDocument::fromJson 解析为 QJsonDocument
    • 根据 JSON 数据的类型(对象或数组)调用 jsonValueToVariant 进行递归转换。
  3. 输出示例

    如果文件 output.json 的内容是:

    json 复制代码
    {
        "key1": "value1",
        "key2": 42,
        "key3": [
            "item1",
            "item2",
            123,
            {
                "nestedKey": "nestedValue"
            }
        ],
        "key4": {
            "subKey1": "subValue1",
            "subKey2": 99
        },
        "key5": true
    }

    那么读取后的 QVariant 数据结构为:

    cpp 复制代码
    QVariantMap {
        "key1": "value1",
        "key2": 42,
        "key3": QVariantList {
            "item1",
            "item2",
            123,
            QVariantMap {
                "nestedKey": "nestedValue"
            }
        },
        "key4": QVariantMap {
            "subKey1": "subValue1",
            "subKey2": 99
        },
        "key5": true
    }

    通过 qDebug() 输出为:

    复制代码
    QMap(("key1", QVariant(QString, "value1"))
         ("key2", QVariant(int, 42))
         ("key3", QVariant(QVariantList, ("item1", "item2", 123, QVariant(QVariantMap, QMap(("nestedKey", QVariant(QString, "nestedValue")))))))
         ("key4", QVariant(QVariantMap, QMap(("subKey1", QVariant(QString, "subValue1")) ("subKey2", QVariant(int, 99)))))
         ("key5", QVariant(bool, true)))
  4. 注意事项

    • 如果文件路径无效或文件格式错误,程序会输出警告。
    • 解析过程中如果遇到不支持的类型,将尝试返回空值。

使用方法:

  1. 运行程序,它会尝试读取 output.json 文件。
  2. 解析后的 QVariant 数据可以直接在程序中使用,也可以通过递归打印函数(如之前的 variantToString)格式化输出。

这样,你就可以将写入的 JSON 文件完整地读取回内存,并转换为 QVariant 数据结构。

相关推荐
用户805533698034 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner4 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz9 天前
QML Hello World 入门示例
qt
xcyxiner12 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner12 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner13 天前
DicomViewer (添加模型类)3
qt
xcyxiner13 天前
DicomViewer (目录调整) 2
qt
xcyxiner13 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
桥田智能15 天前
桥田智能 QT-650S:面向白车身焊装的 800kg 重载快换解决方案
开发语言·qt·系统架构
森G15 天前
75、服务器源码解析---------云视频服务项目
linux·服务器·网络·c++·qt