@Xander84 said in QML and js reading json file and change content "on the go":
I haven't published it yet, but I can just post the code here it isn't that much.
jsonfile.h
@
#ifndef JSONFILE_H
#define JSONFILE_H
#include <QObject>
#include <QFile>
#include <QVariant>
class JsonFile : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(QString fileName READ fileName NOTIFY nameChanged)
Q_PROPERTY(bool exists READ exists)
Q_PROPERTY(bool writeable READ writeable)
Q_PROPERTY(bool readable READ readable)
Q_PROPERTY(qint64 size READ size)
Q_PROPERTY(QString error READ error)
public:
explicit JsonFile(QObject *parent = 0);
JsonFile(const QString &name, QObject *parent = 0);
inline QString name() const { return m_file.fileName(); }
QString fileName() const;
inline bool exists() const { return m_file.exists(); }
inline bool writeable() const { return m_file.permissions().testFlag(QFileDevice::WriteUser); }
inline bool readable() const { return m_file.permissions().testFlag(QFileDevice::ReadUser); }
inline qint64 size() const { return m_file.size(); }
inline QString error() const { return m_error; }
Q_INVOKABLE QString relativeFilePath(const QString &dir = QString()) const;
Q_INVOKABLE bool rename(const QString &newName);
Q_INVOKABLE inline bool copy(const QString &newName) { return m_file.copy(newName); }
Q_INVOKABLE inline bool remove() { return m_file.remove(); }
Q_INVOKABLE bool write(const QVariant &data);
Q_INVOKABLE QVariant read();
signals:
void nameChanged(const QString &name);
public slots:
void setName(const QString &name);
private:
QFile m_file;
QString m_error;
};
#endif // JSONFILE_H
@
jsonfile.cpp
@
#include "jsonfile.h"
#include <QUrl>
#include <QFileInfo>
#include <QDir>
#include <QJsonDocument>
JsonFile::JsonFile(QObject *parent) :
QObject(parent)
{
}
JsonFile::JsonFile(const QString &name, QObject *parent) :
QObject(parent), m_file(name)
{
}
void JsonFile::setName(const QString &name)
{
// fix to convert URL's to local file names
QUrl url(name);
QString localName = url.isLocalFile() ? url.toLocalFile() : name;
if (m_file.fileName() != localName) {
m_file.setFileName(localName);
emit nameChanged(localName);
}
}
QString JsonFile::fileName() const
{
return QFileInfo(m_file).fileName();
}
QString JsonFile::relativeFilePath(const QString &dir) const
{
return QDir(dir).relativeFilePath(m_file.fileName());
}
bool JsonFile::rename(const QString &newName)
{
bool success = m_file.rename(newName);
if (success) {
emit nameChanged(newName);
}
return success;
}
bool JsonFile::write(const QVariant &data)
{
if (m_file.fileName().isEmpty()) {
m_error = tr("empty name");
return false;
}
QJsonDocument doc = QJsonDocument::fromVariant(data);
if (doc.isNull()) {
m_error = tr("cannot convert '%1' to JSON document").arg(data.typeName());
return false;
}
if (doc.isEmpty()) {
m_error = tr("empty data");
return false;
}
QByteArray json = doc.toJson();
if (!m_file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
m_error = tr("cannot open file '%1' for writing: %2")
.arg(m_file.fileName()).arg((m_file.errorString()));
return false;
}
bool success = m_file.write(json) == json.size();
m_file.close();
return success;
}
QVariant JsonFile::read()
{
if (m_file.fileName().isEmpty()) {
m_error = tr("empty name");
return QVariant();
}
if (!m_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
m_error = tr("cannot open file '%1' for reading: %2")
.arg(m_file.fileName()).arg((m_file.errorString()));
return QVariant();
}
QByteArray json = m_file.readAll();
m_file.close();
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(json, &error);
if (error.error != QJsonParseError::NoError) {
m_error = tr("invalid JSON file '%1' at offset %2")
.arg(error.errorString()).arg(error.offset);
return QVariant();
}
return doc.toVariant();
}
@
just register that class in the QML engine, like always in main.cpp or where you do that.
@
qmlRegisterType<JsonFile>("JsonFile", 1, 0, "JsonFile");
@
I think that class should be fairly easy to understand, don't get scared by the amount f properties and methods, most of them are just helper functions as you can see :)
if any error happens (file not found while reading, invalid JSON content, etc) the error message will be available through the "error" property.
Hope that helps :)
which version of qt used for this code?
i tried use that, but received 2 errors:
@
inline QString name() const { return m_file.fileName(); }
/home/isaac/projetos/estudo/teste_tr/jsonfile.h:23: error: C++ requires a type specifier for all declarations
@
@
QString JsonFile::fileName() const
/home/isaac/projetos/estudo/teste_tr/jsonfile.cpp:29: error: out-of-line definition of 'fileName' does not match any declaration in 'JsonFile'
@
I'm using 5.14.1