记录QVariantMap 与 QJsonDocument 读写json文件的相互转换

记录一下

#include <QDebug>
#include <QFile>
#include <QApplication>
#include <QJsonDocument>

void writeFile(QString path, QVariant data)
{
   
   
    QFile file(path);
    if(file.open(QIODevice::WriteOnly|QIODevice::Text))
    {
   
   
        QTextStream stream(&file);
        stream.setCodec("UTF-8");
        QString jsonStr = QJsonDocument::fromVariant(data).toJson
<think>我们正在处理用户的问题:如何在Qt5.14中使用QML进行JSON数据文件读写操作。根据引用内容,我们知道QML是一种声明性语言,它扩展了JavaScript,因此我们可以利用JavaScript的JSON处理能力。但是,QML本身并不直接提供文件读写功能,我们需要借助Qt的模块或其他方式。在QML中,读写文件通常有两种方式:1.使用Qt提供的FileIO模块(QtQuick的FileDialog和FileIO等),但注意,标准的QML并没有内置的FileIO类型,我们需要自己编写C++扩展或者使用第三方库。2.使用XMLHttpRequest(用于读取,写入需要其他方法配合)来读取本地文件(注意跨域问题,但在本地文件系统中可能受限)。然而,在Qt5.14中,我们可以使用以下方法:对于读取:-使用Qt.createQmlObject()动态创建一个组件,然后使用XMLHttpRequest来读取JSON文件(因为QML环境支持XMLHttpRequest,但主要设计用于网络请求,对于本地文件,需要设置正确的路径,并且注意安全限制)。-或者,使用Qt提供的QFile功能通过C++导出给QML使用。对于写入:-同样,我们可以使用XMLHttpRequest发送PUT请求来写入文件?但是这种方法并不常见,而且可能受到限制。-推荐的方法:在C++中实现文件读写操作,然后将该功能导出到QML中。考虑到用户可能希望纯QML解决方案,我们可以尝试使用XMLHttpRequest读取文件(因为读取比较常见),但写入操作在纯QML中比较困难,通常需要C++支持。另外,从Qt5.0开始,QtQuick提供了LocalStorage模块,它使用SQLite来存储数据,但这并不直接支持JSON文件读写。因此,我们给出两种方案:方案一:纯QML(仅读取,写入不推荐)读取:使用XMLHttpRequest读取本地文件(注意:文件路径需要正确,并且应用程序需要有读取权限)。写入:纯QML没有安全的方法写入本地文件,除非使用FileDialog让用户选择保存位置,然后通过XMLHttpRequest发送PUT请求?但这种方法在本地文件系统中可能不可靠。方案二:使用C++和QML结合(推荐)在C++中实现JSON文件读写,然后通过QML的上下文属性或者注册可实例化类型的方式暴露给QML。由于用户要求使用Qt5.14,我们可以利用Qt的C++JSON支持(如QJsonDocument)和文件操作(QFile),然后将这些功能导出到QML。下面我们分别介绍这两种方法。方法一:纯QML读取JSON文件(仅读取)步骤:1.创建一个XMLHttpRequest对象。2.打开请求,指定文件路径(注意:路径可以是相对路径或绝对路径,但在QML中,相对路径是相对于qml文件所在位置,或者使用Qt.resolvedUrl来解析)。3.设置响应类型为JSON(这样会自动解析为JavaScript对象)。4.发送请求,并在onreadystatechange事件处理函数中处理数据。示例代码(读取):```javascriptfunctionreadJSONFile(filePath,callback){varxhr=newXMLHttpRequest();xhr.onreadystatechange=function(){if(xhr.readyState===XMLHttpRequest.DONE){if(xhr.status===200){varjsonData=JSON.parse(xhr.responseText);callback(jsonData,true);}else{console.log("Error:"+xhr.status);callback(null,false);}}};xhr.open("GET",filePath);xhr.send();}//使用示例readJSONFile("data.json",function(data,success){if(success){console.log(JSON.stringify(data));//在这里处理你的数据}});```注意:这种方法在桌面应用和移动应用中可能可行,但在一些平台(如iOS)上,由于安全限制,可能无法读取本地文件(除了应用程序资源目录)。另外,写入文件使用XMLHttpRequest的PUT方法理论上可行,但实际中会遇到权限问题,且不是标准做法。方法二:使用C++和QML结合(读写都支持)步骤:1.创建一个C++类,使用Qt文件JSON功能实现读写操作。2.将该类注册为QML类型或设置为上下文属性。3.在QML中调用该对象的方法。具体实现:1.创建C++类JsonFileHandler:```cpp//jsonfilehandler.h#ifndefJSONFILEHANDLER_H#defineJSONFILEHANDLER_H#include<QObject>#include<QString>#include<QVariant>#include<QFile>#include<QJsonDocument>#include<QJsonObject>#include<QJsonArray>classJsonFileHandler:publicQObject{Q_OBJECTpublic:explicitJsonFileHandler(QObject*parent=nullptr);Q_INVOKABLEQVariantread(constQString&filePath);Q_INVOKABLEboolwrite(constQString&filePath,constQVariant&data);};#endif//JSONFILEHANDLER_H``````cpp//jsonfilehandler.cpp#include"jsonfilehandler.h"JsonFileHandler::JsonFileHandler(QObject*parent):QObject(parent){}QVariantJsonFileHandler::read(constQString&filePath){QFilefile(filePath);if(!file.open(QIODevice::ReadOnly)){qWarning()<<"Couldn'topenfileforreading:"<<filePath;returnQVariant();}QByteArraydata=file.readAll();file.close();QJsonDocumentdoc=QJsonDocument::fromJson(data);if(doc.isNull()){qWarning()<<"FailedtoparseJSONdocument.";returnQVariant();}returndoc.toVariant();}boolJsonFileHandler::write(constQString&filePath,constQVariant&data){QFilefile(filePath);if(!file.open(QIODevice::WriteOnly)){qWarning()<<"Couldn'topenfileforwriting:"<<filePath;returnfalse;}QJsonDocumentdoc=QJsonDocument::fromVariant(data);file.write(doc.toJson());file.close();returntrue;}```2.在main.cpp中注册该类:```cpp#include<QGuiApplication>#include<QQmlApplicationEngine>#include"jsonfilehandler.h"intmain(intargc,char*argv[]){QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);QGuiApplicationapp(argc,argv);qmlRegisterType<JsonFileHandler>("io.qt.json",1,0,"JsonFileHandler");QQmlApplicationEngineengine;engine.load(QUrl(QStringLiteral("qrc:/main.qml")));if(engine.rootObjects().isEmpty())return-1;returnapp.exec();}```3.在QML中使用:```qmlimportio.qt.json1.0JsonFileHandler{id:jsonHandler}//读取functionreadJsonFile(){vardata=jsonHandler.read("path/to/file.json");if(data){console.log("Readdata:",JSON.stringify(data));}}//写入functionwriteJsonFile(){vardataToWrite={name:"Qt",version:5.14};varsuccess=jsonHandler.write("path/to/output.json",dataToWrite);if(success){console.log("Writesuccessful.");}}```注意:文件路径需要根据实际情况设置,可以使用Qt标准路径(如QStandardPaths)来获取合适的存储位置。总结:纯QML方案适合简单的读取操作,但写入操作受限且不推荐。对于完整的读写操作,建议使用C++和QML结合的方式,这样更安全、更灵活。根据用户的问题,我们给出了两种解决方案,用户可以根据自己的需求选择。</think>在 Qt 5.14 中使用 QML 读写 JSON 文件,推荐结合 C++ 后端实现文件操作,并通过 QML 调用。以下是具体实现步骤: ### 方法一:纯 QML 读取(仅读取,不支持写入) ```qml // 读取 JSON 文件文件需放在资源目录或绝对路径) function readJsonFile() { const xhr = new XMLHttpRequest() xhr.open("GET", ":/data.json") // 资源路径 或 绝对路径 xhr.onreadystatechange = function() { if (xhr.readyState === XMLHttpRequest.DONE) { if (xhr.status === 200) { const jsonData = JSON.parse(xhr.responseText) console.log("Name:", jsonData.person.name) } else { console.error("Error reading file") } } } xhr.send() } ``` **限制**: - 仅支持读取,无法写入本地文件 - 文件路径受安全策略限制(推荐使用资源系统 `qrc:/`) --- ### 方法二:C++ 后端实现(推荐,完整读写) #### 1. 创建 C++ JSON 处理器 ```cpp // jsonmanager.h #include <QObject> #include <QFile> #include <QJsonDocument> class JsonManager : public QObject { Q_OBJECT public: Q_INVOKABLE QVariant read(const QString &filePath) { QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) return QVariant(); QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); file.close(); return doc.toVariant(); // 转换QVariantMap/QVariantList } Q_INVOKABLE bool write(const QString &filePath, const QVariant &data) { QFile file(filePath); if (!file.open(QIODevice::WriteOnly)) return false; QJsonDocument doc = QJsonDocument::fromVariant(data); file.write(doc.toJson()); file.close(); return true; } }; ``` #### 2. 注册到 QML 上下文 ```cpp // main.cpp #include "jsonmanager.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); // 注册 JSON 处理器 qmlRegisterType<JsonManager>("Json", 1, 0, "JsonManager"); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec(); } ``` #### 3. QML 调用示例 ```qml import Json 1.0 JsonManager { id: json } // 读取文件 Button { onClicked: { const data = json.read("C:/data/config.json") console.log("Version:", data.appVersion) } } // 写入文件 Button { onClicked: { const newData = { "appVersion": 2.0, "settings": {"theme": "dark"} } json.write("C:/data/config.json", newData) } } ``` ### 关键注意事项 1. **文件路径**: - 桌面端使用绝对路径(如 `C:/data.json`) - 移动端需用 `QStandardPaths` 获取可写目录 2. **数据转换**: - C++ 使用 `QVariantMap`/`QVariantList` QML 对象/数组自动转换 3. **权限**: - 写入时确保应用有文件系统权限 - Linux/macOS 需注意文件所有权 ### 性能优化建议 - 大文件操作使用异步 Worker - 频繁读写可添加内存缓存层 - 敏感数据加密存储(如 QML 的 `LocalStorage`) > 此实现利用了 Qt 的元对象系统实现跨语言调用,通过 `Q_INVOKABLE` 暴露方法,QJsonDocument 处理序列化[^1]。对于纯 QML 方案,XMLHttpRequest 仅建议读取资源文件,因浏览器安全限制无法写入本地文件系统[^2]。 --- ### 相关问题 1. QML 如何实现 JSON 数据 ListModel 的绑定? 2. 在 Android/iOS 上如何安全存储 JSON 配置文件? 3. Qt 中是否有替代 XMLHttpRequest 的异步文件读取方案? 4. 如何优化大 JSON 文件(>10MB)的解析性能? [^1]: QML 提供了高可读性的、声明式的、类 Json 的语法,支持结合了动态属性绑定的 JavaScript 表达式。 [^2]: QML 是一种说明性语言,用来描述基于 Qt 对象系统的用户界面。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值