复杂的QVariant写入文件以及从文件中读入复原
将复杂的QVariant写入Json文件
要将复杂的 QVariant
(包含 QList
和 QMap
等)写入 JSON 文件,你可以借助 Qt 的 QJsonDocument
、QJsonObject
和 QJsonArray
将 QVariant
转换为 JSON 格式。以下是实现代码:
实现代码:
#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;
}
说明:
-
核心方法:
variantToJsonValue
- 这是一个递归函数,将
QVariant
转换为QJsonValue
。 - 支持以下类型:
QVariant::Map
-> 转换为QJsonObject
QVariant::List
-> 转换为QJsonArray
- 基本类型(
QString
、int
、double
、bool
) -> 转换为对应的 JSON 值 - 对于其他类型,尝试调用
toString()
进行转换,如果不支持则写入空值。
- 这是一个递归函数,将
-
JSON 文件写入:
writeVariantToJsonFile
- 使用
QJsonDocument
将QJsonValue
写入 JSON 文件。 - 自动判断数据结构是 JSON 对象还是数组,如果是其他类型,则将其包装为一个 JSON 对象。
- 通过
QJsonDocument::Indented
格式化输出,生成可读性更高的 JSON 文件。
- 使用
-
支持的类型
QVariantMap
-> JSON 对象QVariantList
-> JSON 数组- 基本类型(
QString
、int
、double
、bool
等)
-
输出示例
假设输入的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;
输出的
output.json
文件内容为:{ "key1": "value1", "key2": 42, "key3": [ "item1", "item2", 123, { "nestedKey": "nestedValue" } ], "key4": { "subKey1": "subValue1", "subKey2": 99 }, "key5": true }
-
注意事项
- 如果文件路径无效或者没有写入权限,会发出警告。
QVariant
中包含无法识别的类型时,将尝试将其转换为字符串,否则写入空值。
使用方法:
将上述代码复制并运行,程序会将复杂的 QVariant
数据结构写入 output.json
文件,你可以用任意文本编辑器或 JSON 查看器打开文件查看结果。
从Json文件中复原QVariant
要将刚才写入的 JSON 文件重新读入到程序中,并解析为一个 QVariant
数据结构,可以使用 Qt 的 QJsonDocument
和 QJsonObject
/QJsonArray
类。以下是实现代码:
实现代码:
#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;
}
说明:
-
核心方法:
jsonValueToVariant
- 递归地将
QJsonValue
转换为QVariant
。 - 支持以下类型:
QJsonObject
-> 转换为QVariantMap
QJsonArray
-> 转换为QVariantList
- 基本类型(字符串、数字、布尔值等) -> 转换为对应的
QVariant
类型 - 空值(
null
) -> 转换为默认的QVariant()
- 递归地将
-
从 JSON 文件读取:
readJsonFileToVariant
- 读取 JSON 文件内容到内存。
- 使用
QJsonDocument::fromJson
解析为QJsonDocument
。 - 根据 JSON 数据的类型(对象或数组)调用
jsonValueToVariant
进行递归转换。
-
输出示例
如果文件output.json
的内容是:{ "key1": "value1", "key2": 42, "key3": [ "item1", "item2", 123, { "nestedKey": "nestedValue" } ], "key4": { "subKey1": "subValue1", "subKey2": 99 }, "key5": true }
那么读取后的
QVariant
数据结构为: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)))
-
注意事项
- 如果文件路径无效或文件格式错误,程序会输出警告。
- 解析过程中如果遇到不支持的类型,将尝试返回空值。
使用方法:
- 运行程序,它会尝试读取
output.json
文件。 - 解析后的
QVariant
数据可以直接在程序中使用,也可以通过递归打印函数(如之前的variantToString
)格式化输出。
这样,你就可以将写入的 JSON 文件完整地读取回内存,并转换为 QVariant
数据结构。