0

I am trying to do a simple programming to parse JSON message value from web to Qt Quick.

The JSON message would like to parse:

[
    {
         "id": 2,
         "name": "yahoo",
         "link": "http://www.yahoo.com/",
         "created_by": "superadmin",
         "create_time": "2015-03-12 14:45:21"
    },
    {
         "id": 3,
         "name": "Google",
         "link": "http://www.google.com/",
         "created_by": "superadmin",
         "create_time": "2015-03-12 14:45:41"
    },
    {
         "id": 4,
         "name": "PS",
         "link": "http://www.playstation.com",
         "created_by": "superadmin",
         "create_time": "2015-03-24 11:57:21"
    }
]

The following is the Qt code main.cpp to try to parse these data:

#include <QGuiApplication>
#include <QStringList>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QtScript/QScriptEngine>
#include <QtScript/QScriptValueIterator>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <qqmlengine.h>
#include <qqmlcontext.h>
#include <qqml.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
#include <main.h>



QStringList Jsondata::datalistmethod() {

   return datalist;
}


void Jsondata::onResult(QNetworkReply* reply)
{

    QString data = (QString) reply->readAll();


    QJsonDocument jsonResponse = QJsonDocument::fromJson(data.toUtf8());
    QJsonObject jsonObject = jsonResponse.object();


    foreach (const QJsonValue & value, jsonObject) {
        QJsonObject obj = value.toObject();
        datalist.append(obj["name"].toString());
        datalist.append(obj["link"].toString());
    }
}

int main(int argc, char ** argv)
{
    QGuiApplication app(argc, argv);
    Jsondata jsondata;
    // Now parse this JSON according to your needs !
   QNetworkAccessManager networkManager;
   networkManager.setNetworkAccessible(QNetworkAccessManager::Accessible);

   QUrl url("http://dbs.wasonicsystem.com/gta_test/api/web/v1/links");
   QNetworkRequest request;
   request.setUrl(url);

   Jsondata::connect(&networkManager, SIGNAL(finished(QNetworkReply*)), &jsondata, SLOT(onResult(QNetworkReply*)));
    networkManager.get(request);   // GET

    QStringList datalist;
    datalist = jsondata.datalistmethod();

    QQuickView view;
    QQmlContext *ctxt = view.rootContext();
    ctxt->setContextProperty("myModel", QVariant::fromValue(datalist));

    view.setSource(QUrl("qrc:main.qml"));
    view.show();

    return app.exec();
}

main.h

#ifndef MAIN
#define MAIN
#include <QObject>
#include <QNetworkReply>
#include <QStringList>
class Jsondata : public QObject {
    Q_OBJECT
    QStringList datalist;
public slots:
    void onResult (QNetworkReply*);
public:
    QStringList datalistmethod();
};
#endif // MAIN

main.qml

import QtQuick 2.0
//![0]

ListView {
    width: 100; height: 100

    model: myModel
    delegate: Rectangle {
        height: 25
        width: 100
        Text { text: modelData }
    }
}
//![0]

Results in: onResult still not called. so no datalist returned

I don't have knowledge on this QObject::connect and don't know what wrong. I would appreciate it if you could help me to fix this bug.

Lapson Wong
  • 107
  • 11
  • 3
    You're trying to create a connection to an object that doesn't derive from `QObject` (your `JsonData` class). Of course you could have just looked at the docs: http://doc.qt.io/qt-5/qobject.html#connect – cmannett85 Apr 21 '15 at 08:23
  • 2
    It is very strange that you call `QObject::connect(&networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onResult(QNetworkReply*)));` inside `onResult` slot. Looks like the logic of your application is broken. – Nikita Apr 21 '15 at 08:50
  • Thank you for your answer. I tried to derive from Qobject. It fix the error. But I still cannot get the result from the json message since I found that it didn't call onResult method. I modify the code posted and added main.qml fyi. I hope anyone can help me to complete it. Thank you. – Lapson Wong Apr 22 '15 at 07:03
  • hi all, i use another way and edited my question again, but the onResult still not triggered during connect. Please let me know if you have any ideas to solve the problem. Thank you. – Lapson Wong Apr 24 '15 at 07:09
  • There's a lot of opportunity for failure in your code and no error checking. – Retired Ninja Apr 24 '15 at 07:22
  • Would you please suggest a way to check the bugs? I tried to set breakpoint and debug in iPhone simulator. However, neither put the connect into the datalist method nor main method can trigger the onResult Slot. > – Lapson Wong Apr 24 '15 at 07:54
  • Many of those calls have return values you could check for errors, and you could connect the onError signal. You didn't mention you were running this in a simulator, that could be interfering as well. – Retired Ninja Apr 24 '15 at 08:02

1 Answers1

0

I finally found a method to solve the problem. The following is the code snippet.

main.cpp

#include <QGuiApplication>
#include <QStringList>
#include <qqmlengine.h>
#include <qqmlcontext.h>
#include <qqml.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
#include <jsondata.h>

int main(int argc, char ** argv)
{
    QGuiApplication app(argc, argv);
    QStringList datalist;
    Jsondata jsondata;
    jsondata.datalistmethod();
    datalist = jsondata.datalist;

    QQuickView view;
    QQmlContext *ctxt = view.rootContext();
    ctxt->setContextProperty("myModel", QVariant::fromValue(datalist));
    view.setSource(QUrl("qrc:main.qml"));
    view.show();

    return app.exec();

}

jsondata.h

#ifndef JSONDATA_H
#define JSONDATA_H
#include <QObject>
#include <QNetworkReply>
#include <QStringList>
#include <QNetworkAccessManager>
class Jsondata : public QObject {
    Q_OBJECT
public:
    QStringList datalist;
    explicit Jsondata(QObject *parent =0);
    void datalistmethod();
public slots:
    void onResult (QNetworkReply*);

private:
    QNetworkAccessManager *manager;
};

jsondata.cpp

#include "jsondata.h"
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QEventLoop>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
#include <QTimer>
#include <qqmlengine.h>
#include <qqmlcontext.h>
#include <qqml.h>

Jsondata::Jsondata(QObject *parent) :
    QObject(parent)
{

}


void Jsondata::datalistmethod() {
    // Now parse this JSON according to your needs !
   manager = new QNetworkAccessManager(this);

   manager->setNetworkAccessible(QNetworkAccessManager::Accessible);
    QNetworkRequest request;
   QEventLoop eventloop;
   QUrl url("http://***/api/web/v1/links");
    request.setUrl(url);
     QNetworkReply *reply = manager->get(request);
   connect(reply, SIGNAL(finished()), &eventloop, SLOT(quit()));
   eventloop.exec();
   onResult(reply);

}


void Jsondata::onResult(QNetworkReply* reply)
{
    QString data = (QString) reply->readAll();
    qDebug() << "Response:" << data;
    QJsonDocument jsonResponse = QJsonDocument::fromJson(data.toUtf8());
    QJsonArray jsonArray = jsonResponse.array();
    foreach (const QJsonValue & value, jsonArray) {
        QJsonObject obj = value.toObject();
        datalist.append(obj["name"].toString());
        datalist.append(obj["link"].toString());
    }
}

By adding event loop, the datalist method will wait for the onResult method completed to execute next line of code. This is using the example of string list model. If anyone feel it useful for reference, please +1 my post. Thank you. ^^

Lapson Wong
  • 107
  • 11