I'm trying to pull JSON data from a URL using the Qt framework, and I've run into some issues with getting a return from the get request. I've seen multiple questions asked regarding my issue, but none of the given solutions has solved my problem.
So I have a button that, once clicked, should execute the get request. Here's my code.
//When button is pressed
void Test1::onClickCapture()
{
qDebug() << "Capture Clicked!!";
toPopulate();
}
//Code to execute the connection
void Test1::toPopulate() {
qDebug() << "Populating!";
QNetworkAccessManager* manager = new QNetworkAccessManager(this);
QNetworkRequest request;
QUrl url("https://jsonplaceholder.typicode.com/posts/1");
request.setUrl(url);
QNetworkReply *reply = manager->get(request);
connect(reply, &QNetworkReply::readyRead, this, &Test1::onResult);
}
//And finally, my onResult slot
void Test1::onResult() {
reply->deleteLater();
if (reply->error() != QNetworkReply::NoError) {
return;
}
qDebug() << "Response!";
}
Every time I debug the code, it never gets to my onResult slot.
I also get this error, which may be relevant.
QObject::connect: Cannot connect (null)::aboutToQuit() to QNativeWifiEngine::closeHandle()
I have modified your code. It's working fine for me:
//Code to execute the connection
void MainWindow::toPopulate() {
qDebug() << "Populating!";
QNetworkAccessManager* manager = new QNetworkAccessManager(this);
QNetworkRequest request;
QUrl url("https://jsonplaceholder.typicode.com/posts/1");
request.setUrl(url);
QNetworkReply *reply = manager->get(request);
connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(downloading(qint64,qint64)));
connect(reply, SIGNAL(finished()), this, SLOT(onResult()));
}
void MainWindow::downloading(qint64 bytesReceived, qint64 bytesTotal) {
qDebug() << "Downloading " << bytesReceived/bytesTotal*100 << " %.";
}
//And finally, my onResult slot
void MainWindow::onResult() {
QNetworkReply* reply = qobject_cast<QNetworkReply*> (QObject::sender());
if (reply->error() != QNetworkReply::NoError) {
qDebug() << "Error downloading. " << reply->errorString();
return;
}
reply->deleteLater();
qDebug() << "Response! " << reply->readAll();
}
Result:
Populating!
Downloading -29200 %.
Downloading 100 %.
Response! "{\n \"userId\": 1,\n \"id\": 1,\n \"title\": \"sunt aut facere repellat provident occaecati excepturi optio reprehenderit\",\n \"body\": \"quia et suscipit\\nsuscipit recusandae consequuntur expedita et cum\\nreprehenderit molestiae ut ut quas totam\\nnostrum rerum est autem sunt rem eveniet architecto\"\n}"
Related
I want to send a put request with JSON body, but with QNetworkAccessManager doesn't have the option to send a request with JSON so I converted it to QByteArray, the structure of the body, when converted to QByteArray, is not a JSON format so that I received an Error with
"Error downloading https://example.api.com/something/DataSet('123456780XYZ') - server replied: Forbidden"
The JSON format I want is like this:
{
"d": {
"Duration": "0.000",
"Id": "123456780XYZ",
"LoadCumulLimit": "0.000",
"Notes": "send from postman in Json format"
}
}
Here is what did I do
QJsonObject data;
data["Duration"] = workplace->data["duration"];
data["Id"] = id;
data["LoadCumulLimit"] = workplace->data["load_cumul_limit"];
data["Notes"] = workplace->dataText["Notes"];
QJsonObject newData;
newData["d"] = data;
QJsonDocument doc(newData);
qDebug() << url;
QByteArray finalData = doc.toJson();
qDebug() << finalData;
reply = manager->put(request, finalData);
connect(reply, &QNetworkReply::finished, [=](){
if(reply->error() == QNetworkReply::NoError){
QString contents = QString::fromUtf8(reply->readAll());
qDebug() << contents;
}
else{
QString err = reply->errorString();
qDebug() << err;
}
reply->deleteLater();
});
But I received the QByteArray like this:
"{\n \"d\": {\n \"Duration\": 8,\n \"IgelId\": \"123456780XYZ\",\n \"LoadCumulLimit\": 25,\n \"Notes\": \"send from IGEL\"\n }\n}\n"
But it does not get the data from the database. I'm do not want to retrieve the data to the table and want to display data in particular line edit. What is the error? Is there any modification?
This is the Code that I'm using:
void Userdetails::on_pushButton_4_clicked()
{
delete ui;
// database connection
database = QSqlDatabase::addDatabase("QMYSQL");
database.setHostName("localhost");
database.setUserName("root");
database.setPassword("");
database.setDatabaseName("electricity");
if(database.open()) {
QSqlQuery qry;
QSqlQuery query(QSqlDatabase::database("MyConnect"));
query.prepare(QString("SELECT accno, fullname, address, telephone FROM user_reg_elec WHERE username = :username AND password = :password"));
if(query.exec()) {
query.exec();
while(query.next()) {
ui ->dislayaccountnumber ->setText(query.value(0).toString());
ui ->displayname ->setText(query.value(3).toString());
ui ->displayaddress ->setText(query.value(4).toString());
ui ->displattelephoneno ->setText(query.value(5).toString());
// ui ->displayamountoebill ->setText(query.value(6).toString());
}
} else {
QMessageBox::information(this, "Query did not execute", "Not successful executing the query");
}
} else {
QMessageBox::information(this, "Database not open", "Not opened successfully");
}
database.close();
}
This code has four main issues:
You have deleted the ui at the beginning of your code. Hence, the first line that calls ui-> will crash the program.
You have defined your query improperly. Also, your way to select a name for your connection is not right.
You have executed your query twice (one is enough).
You've not bind values for username and password.
Please use the following:
void Userdetails::on_pushButton_4_clicked() {
{
// database connection
QSqlDatabase database;
database = QSqlDatabase::addDatabase("QMYSQL","MyConnect");
database.setHostName("localhost");
database.setUserName("root");
database.setPassword("");
database.setDatabaseName("electricity");
if(database.open()) {
QSqlQuery query(database);
if (query.prepare(QString("SELECT accno, fullname, address, telephone FROM user_reg_elec WHERE username = :username AND password = :password"))) {
//Add bindings
query.bindValue(":username","your user name");
query.bindValue(":password","your password");
if(query.exec()) {
while(query.next()) {
ui ->dislayaccountnumber ->setText(query.value(0).toString());
ui ->displayname ->setText(query.value(1).toString());
ui ->displayaddress ->setText(query.value(2).toString());
ui ->displattelephoneno ->setText(query.value(3).toString());
// ui ->displayamountoebill ->setText(query.value(4).toString());
}
} else {
qDebug() << "Query did not execute due to: " << query.lastError().text();
QMessageBox::information(this, "Query did not execute", "Not successful executing the query");
}
} else {
qDebug() << "Query not prepared due to the following error: " << query.lastError().text();
}
} else {
qDebug() << "Database not opened due to: " << database.lastError().text();
QMessageBox::information(this, "Database not open", "Not opened successfully");
}
database.close();
}
QSqlDatabase::removeDatabase("MyConnect");
}
Please add #include <QSqlError> to the top, if you have not already included this library.
Only to the questionary:
To show details in a new window, after you got the target user's information from your database, you can create a new dialog (window) and show the results in it as follows:
//Create a new dialog
QDialog *dialog = new QDialog;
//Add some elements to the dialog
QLabel *accountNumber = new QLabel("Account number: " + query.value(0).toString());
QLabel *name = new QLabel("Name: " + query.value(1).toString());
QLabel *address = new QLabel("Address: " + query.value(2).toString());
QLabel *phoneNumber = new QLabel("Phone number: " + query.value(3).toString());
QVBoxLayout *lay = new QVBoxLayout;
lay->addWidget(accountNumber);
lay->addWidget(name);
lay->addWidget(address);
lay->addWidget(phoneNumber);
dialog->setLayout(lay);
//Show the dialog
dialog->open();
I'm trying to insert an event to google calendar using Qt C++.
Before inserting events, I am able to clear the primary calendar using these lines
const QUrl clearPrimaryUrl("https://www.googleapis.com/calendar/v3/calendars/primary/clear");
void GoogleWrapper::clearPrimaryCalendar()
{
QNetworkReply *reply = google.post(clearPrimaryUrl);
connect(reply, &QNetworkReply::finished, [=]()
{
reply->deleteLater();
if(reply->error() != QNetworkReply::NoError)
{
qCritical() << "Google error:" << reply->errorString();
return;
}
emit primaryCalendarCleared();
});
}
google is an QOAuth2AuthorizationCodeFlow object.
Now to insert events, I use these lines:
const QUrl insertEventUrl("https://www.googleapis.com/calendar/v3/calendars/primary/events");
void GoogleWrapper::insertEvent(const QByteArray &eventData)
{
qDebug() << eventData;
QNetworkReply *reply = google.post(insertEventUrl, eventData);
connect(reply, &QNetworkReply::finished, [=]()
{
reply->deleteLater();
if(reply->error() != QNetworkReply::NoError)
{
qCritical() << "Google error:" << reply->errorString();
return;
}
emit eventInserted();
});
}
But the output I received from qCritical was always Error transferring https://www.googleapis.com/calendar/v3/calendars/primary/events - server replied: Bad Request.
I tried output the eventData to a file and copy paste it to Google's try this API and the below json data works perfectly
{
"description": "some teacher name",
"end": {
"dateTime": "2018-12-19T11:15:00Z"
},
"location": "Room",
"start": {
"dateTime": "2018-12-19T09:30:00Z"
},
"summary": "Subject Name"
}
Anyone have any idea what I did wrong?
The issue is solved thanks to #thuga's comment.
My code was missing the line
google.setContentType(QAbstractOAuth2::ContentType::Json);
I am writing a simple qt network application. I try to read the data from the QNetworkReply but it seems that the finished signal never emit. What happens?
QByteArray utils::Login(QString account)
{
QNetworkAccessManager* manager = new QNetworkAccessManager();
QNetworkRequest* request = new QNetworkRequest();
request->setUrl(QUrl(Urls::loginUrl));
request->setRawHeader("Host", "10.136.2.5");
request->setRawHeader("Referer", "http://10.136.2.5/jnuweb/");
request->setRawHeader("Content-Type", "application/json; charset=utf-8");
request->setRawHeader("Connection", "keep-alive");
request->setRawHeader("X-Requested-With", "XMLHttpRequest");
request->setRawHeader("Accept", "*/*");
request->setRawHeader("Accept-Encoding", "deflate");
QJsonObject* requestContent = new QJsonObject();
requestContent->insert("user", QJsonValue(account));
requestContent->insert("password", QJsonValue(Urls::initPassword));
QNetworkReply* reply = manager-> post(*request, QJsonDocument(*requestContent).toJson(QJsonDocument::Compact));
QObject::connect(reply, &QNetworkReply::finished, [=]()
{
QList<QPair<QByteArray, QByteArray>> responses = reply -> rawHeaderPairs();
qDebug() << responses;
});
}
I am trying to send http POST request. Here is code snippets:
const QUrl URL("https://httpbin.org/post");
QNetworkRequest req(URL);
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QUrlQuery urlQuery;
urlQuery.addQueryItem ("username", username);
urlQuery.addQueryItem ("password", password);
QUrl params;
params.setQuery (urlQuery);
mNetReply = mNetMan->post(req, params.toEncoded());
and here is the response output:
QJsonObject({"args":{},"data":"","files":{},"form":{"?username":"xyz","password":"xyz"},"headers":{"Accept-Encoding":"gzip, deflate","Accept-Language":"en-US,*","Connection":"close","Content-Length":"28","Content-Type":"application/x-www-form-urlencoded","Host":"httpbin.org","User-Agent":"Mozilla/5.0"},"json":null,"origin":"*.*.*.*","url":"https://httpbin.org/post"})
My problem is , qt automatically adding a ? mark in first queryItem.
For what it's worth still, because an answer was not given:
Don't use the conversion to a QUrl, using the QUrlQuery directly solved the problem for me.
urlQuery.toString(QUrl::FullyEncoded).toUtf8()
in stead of
params.toEncoded()
Total snippet updated:
const QUrl URL("https://httpbin.org/post");
QNetworkRequest req(URL);
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QUrlQuery urlQuery;
urlQuery.addQueryItem ("username", username);
urlQuery.addQueryItem ("password", password);
mNetReply = mNetMan->post(req, urlQuery.toString(QUrl::FullyEncoded).toUtf8());