Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. QML and js reading json file and change content "on the go"
Forum Updated to NodeBB v4.3 + New Features

QML and js reading json file and change content "on the go"

Scheduled Pinned Locked Moved QML and Qt Quick
13 Posts 3 Posters 15.2k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • X Offline
    X Offline
    Xander84
    wrote on last edited by
    #4

    yeah you should be able to use XMLHttpRequest and JSON.parse if you don't want any c++ in your project :D
    I just made my own c++ plugin because XMLHttpRequest has some limitations, you can't easily check if a file exists and you cant write to files with it I think (so only read access), but in your case that should be fine so just use it I guess.

    Just if you want to know how my JsonFile plugin looks like in QML:
    @
    JsonFile {
    id: jsonFile
    name: "foo.json"
    }

    ...

    jsonFile.write([1,2,3]) // write any JavaScript array or object
    var data = jsonFile.read() // read JSON file into JavaScript object or array
    @

    it is easy to use from QML, not that the c++ part is complicated, but is has some helper functions and stuff like jsonFile.size (file size) or jsonFile.exists and some other stuff.

    1 Reply Last reply
    0
    • V Offline
      V Offline
      vitorcarvalhoml
      wrote on last edited by
      #5

      the problem is the update of the json file. Read it again and then change the slide content.

      I know it's ask too much, but can someone put some simple code example?

      1 Reply Last reply
      0
      • X Offline
        X Offline
        Xander84
        wrote on last edited by
        #6

        I don't know what you mean by update of the file, what changes the JSON file? if the file is dynamically changed outside of your application you have to use a file watcher or or poll the contents every 'x' seconds, that is not possible with QML. Maybe I understand you wrong, sounds a little weird with your JSON file!?

        1 Reply Last reply
        0
        • V Offline
          V Offline
          vitorcarvalhoml
          wrote on last edited by
          #7

          I would love to download your plugin. How can I add it to my project?

          1 Reply Last reply
          0
          • X Offline
            X Offline
            Xander84
            wrote on last edited by
            #8

            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(&#41; 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 :)

            Y 1 Reply Last reply
            0
            • V Offline
              V Offline
              vitorcarvalhoml
              wrote on last edited by
              #9

              That help me a lot! Thanks! But how can I print the json content (debug)?

              1 Reply Last reply
              0
              • X Offline
                X Offline
                Xander84
                wrote on last edited by
                #10

                the raw JSON content is only available in the c++ file, look at the method JsonFile::read()
                @
                QByteArray json = m_file.readAll();
                @
                that json variable holds the content of the file, you can print it to the console with
                @
                qDebug() << json;
                @
                might need to include QDebug for that
                @
                #include <QDebug>
                @
                at the top of the file (I don't know how much c++ you know?)

                if you rather want to print the parsed content as JavaScript object or array you can just to that in QML?

                1 Reply Last reply
                0
                • V Offline
                  V Offline
                  vitorcarvalhoml
                  wrote on last edited by
                  #11

                  I "read" the JSON file in Qml but the content it's available in C++ file?

                  My knowledge in C++ it's almost nothing :(

                  1 Reply Last reply
                  0
                  • X Offline
                    X Offline
                    Xander84
                    wrote on last edited by
                    #12

                    well to explain that a little, everything that comes from outside of QML (a file on your disk, network etc) goes through c++, you might not see it but If you use an Image in QML the file gets loaded and decoded in c++ and then transferred to QML.

                    Usually you don't need to see the raw JSON content, so the question here is what you want do to? You can just debug the decoded JSON object/array in QML, that should be fine unless there is an error and you need to know why.
                    In that case you should learn how to use the debugger with QML and c++, you can just set a breakpoint in Qt Creator and see the value at that point without printing the value to the console. You might want to read this article about debugging in QML http://qt-project.org/doc/qt-5.0/qtquick/qtquick-debugging.html

                    For simple debug purposes of javaScript objects your can also use
                    @
                    JSON.stringify(obj)
                    // use it with my JsonFile like this
                    console.log(JSON.stringify(jsonFile.read()))
                    @
                    that might look stupid to parse the JSON string and then convert it back to a string, but it is the easiest way for debugging purposes since the console cannot print objects (you will just see [object Object] or something simular).

                    1 Reply Last reply
                    0
                    • X Xander84

                      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(&#41; 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 :)

                      Y Offline
                      Y Offline
                      Ysaakue
                      wrote on last edited by Ysaakue
                      #13

                      @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(&#41; 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

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved