Qt Json Parsing c++ - c++

I am trying to parse json object in QT from an api. However when i try the codes written below i cannot parse the object. I simply want to get the information stored in those parameters.
API is
{
"error": {
"errorcode": 0,
"errorstring": ""
},
"login": 1,
"logintoken": "209b06aa7f059673db393ff7a731af1847344903b9733f026cc3a6f7a5b797b3"
}
The Codes are
QUrl ava_url("http://pinundpin.de/wsdemo/atgdemoapi_v3/index.php");
QNetworkRequest ava_request(ava_url);
ava_request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
QNetworkAccessManager *manager = new QNetworkAccessManager();
QEventLoop loop;
QObject::connect(manager,
SIGNAL(finished(QNetworkReply *)),
&loop,
SLOT(quit()));
QByteArray postData;
Username = "testwebser";
Passwd = "2017#QWEasdZXC";
postData.append("action=login&");
postData.append("password="+Passwd+"&");
postData.append("username="+Username);
QNetworkReply* reply = manager->post(ava_request,postData);
loop.exec();
QString response = (QString)reply->readAll();
qDebug()<< response;
QJsonDocument temp = QJsonDocument::fromJson(response.toUtf8());
QJsonObject jsonObj = temp.object();
qDebug() <<"error"<< jsonObj["error"].toString();
qDebug() <<"login"<< jsonObj["login"].toString();
qDebug() << "logintoken"<<jsonObj["logintoken"].toString();
the response string looks
and the output is
D/libAndroisShop.so(21944): ../AndroisShop/networkconnection.cpp:45 (QString NetworkConnection::Connect(QString, QString)): "<br><br>NO OF ROWDATA: 1{\"error\":{\"errorcode\":0,\"errorstring\":\"\"},\"login\":1,\"logintoken\":\"4daaf6b3dd5a26a2ad2c436e564bfa4d6c439ce4d0d6cd66705a8bdadddddaa0\"}"
D/libAndroisShop.so(21944): ../AndroisShop/networkconnection.cpp:50 (QString NetworkConnection::Connect(QString, QString)): error ""
D/libAndroisShop.so(21944): ../AndroisShop/networkconnection.cpp:51 (QString NetworkConnection::Connect(QString, QString)): login ""
D/libAndroisShop.so(21944): ../AndroisShop/networkconnection.cpp:52 (QString NetworkConnection::Connect(QString, QString)): logintoken ""
Postman Image

If you review the result of POSTMAN in raw mode you get the following:
What QNAM gets but POSTMAN has another algorithm to extract the json:
So a possible solution is to remove the unwanted element: <br><br>NO OF ROWDATA: 1, for this it takes advantage that the json must start with "{" so the superior substring is used.
QUrl ava_url("http://pinundpin.de/wsdemo/atgdemoapi_v3/index.php");
QNetworkRequest ava_request(ava_url);
ava_request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
QNetworkAccessManager *manager = new QNetworkAccessManager();
QEventLoop loop;
QObject::connect(manager,
&QNetworkAccessManager::finished,
&loop,
&QEventLoop::quit);
QByteArray postData;
QString Username = "testwebser";
QString Passwd = "2017#QWEasdZXC";
postData.append("action=login&");
postData.append("password="+Passwd+"&");
postData.append("username="+Username);
QNetworkReply *reply = manager->post(ava_request,postData);
loop.exec();
QByteArray response = reply->readAll();
QByteArray json = response.mid(response.indexOf("{"));
QJsonDocument temp = QJsonDocument::fromJson(json);
QJsonObject jsonObj = temp.object();
QJsonObject errorObj = jsonObj["error"].toObject();
qDebug()<<"error: "
<<"errorcode: "<< errorObj["errorcode"].toInt()
<<"errorstring: "<< errorObj["errorstring"].toString();
qDebug() <<"login"<< jsonObj["login"].toInt();
qDebug() << "logintoken"<<jsonObj["logintoken"].toString();
Output:
error: errorcode: 0 errorstring: ""
login 1
logintoken "cc7e46f34e0a268cecbaaeaad41b0ae2727cc7196b632574a4db16544576d012"

Related

issue with reading a data from web page

I want to read a string from html source of https web page.
Here is my code:
QString qmldialogue::readPage(QString page)
{
QString url = "https://my link here";
QNetworkAccessManager manager;
QNetworkReply *response = manager.get(QNetworkRequest(QUrl(url)));
QEventLoop event;
connect(response, SIGNAL(finished()), &event, SLOT(quit()));
event.exec();
QByteArray bytes = response->readAll();
QString str = QString::fromUtf8(bytes.data(), bytes.size());
int statusCode = response->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
qDebug()<<str;
qDebug() << QVariant(statusCode).toString();
return str;
}
Everything seems to be working, but for some reason the content of the html tags I need is empty:
...class=\"status-value cert-name\"></span></div>...
If I manually download the html file of the page, then everything will be as I need:
...class="status-value cert-name">Valid until termlessly</span></div>...
Int statusCode value is 200.
What am I doing wrong?

Wait till request finished Qt

My program is getting data from mysql table via json format through php script, that generating json.
My function sends to server post request (with some params) and getting response. With that all okay. Works fine.
But, when I want to get specified cell (data from json array), it takes empty string (program works fast and taking data from a string before it sets up)
Here's the code with post request:
void dbase::requestor(QString option)
{
curr_js = ""; //nulling string
QString urla = host+"transfer.php";
// /////////
QNetworkAccessManager * manager = new QNetworkAccessManager(this);
QUrl url(urla);
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QUrlQuery params;
params.addQueryItem("api", key);
params.addQueryItem("option", option);
//QEventLoop loop;
connect(manager, SIGNAL(finished(QNetworkReply *)),this, SLOT(replyFinished(QNetworkReply *)));
//loop.exec(); tryed eventloop, but bcuz of this my replyFinished is not accessible. error code under this one
manager->post(request, params.query().toUtf8());
}
If using eventloop
QObject::connect: No such slot QEventLoop::replyFinished(QNetworkReply *)
replyFinished function (setting up variable)
void dbase::replyFinished(QNetworkReply *reply)
{
curr_js = reply->readAll();
}
Usage (where is problem)
QString req = "SOME REQUEST";
database.requestor(req);
if (database.db_cell (0,0) == "")
{
qDebug()<<database.db_cell (0,0) << " - EMPTY - "<<database.curr_js;
}
So in this case I'm getting
"" - EMPTY - ""
But if I getting data from string (created button for test), it's there:
{"0":["1", "Admin","hashpwd"],"1":["2", "Albert","hashpwd"]}
db_cell function
QString dbase::db_cell (int indexrow, int indexcols)
{
QJsonDocument sd = QJsonDocument::fromJson(curr_js.toUtf8());
QJsonObject setobj = sd.object();
QJsonValue qqq = setobj.value(QString(QString::number(indexrow))).toArray()[indexcols];
return qqq.toString();
}
As I see, problem is that program need to wait before getting a data from json-string.

get multiple data from json with QT C++

I need to get a multiple data from json, the first part I can read, but the json inside I can't get it.
So my data from API:
My code in c++/QT it's the next:
QString JsonFunctions::getUnits(QString token_type, QString access_token)
{
QString lista;
QEventLoop eventLoop;
QNetworkAccessManager mgr;
QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));
QJsonObject json;
QNetworkRequest request(QUrl("https://MYURL/api/v2/units"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
//request.setRawHeader("Content-Type", "application/json");
request.setRawHeader("Accept", "application/json");
QString sing = token_type + " " + access_token;
request.setRawHeader("Authorization", sing.toUtf8());
QSslConfiguration conf = request.sslConfiguration();
conf.setPeerVerifyMode(QSslSocket::VerifyNone);
request.setSslConfiguration(conf);
QNetworkReply *reply = mgr.get(request);
eventLoop.exec();
QString strReply = (QString)reply->readAll();
qDebug() << "reply" << strReply;
qDebug() << "code" << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QJsonDocument jsonResponse = QJsonDocument::fromJson(strReply.toUtf8());
QJsonArray jsonArray = jsonResponse.array();
QJsonObject jsonObject = jsonResponse.object();
QVariantMap mainmap = jsonObject.toVariantMap();
QVariantList phraseList = mainmap["data"].toList();
QJsonObject jsonobjs = QJsonObject::fromVariantMap(mainmap);
QJsonArray dataObject = jsonobjs.value("data").toArray();
for(int i = 0; i < dataObject.count(); i++){
QJsonObject temp = dataObject[i].toObject();
units unitsTemp;
unitsTemp.id = temp.value("ac_role_name").toString();
unitsTemp.description = temp.value("description").toString();
unitsTemp.thing_name = temp.value("thing_name").toString();
unitsTemp.serial_number = temp.value("serial_number").toString();
unitsTemp.access_key = temp.value("access_key").toString();
unitsTemp.state = temp.value("state").toInt();
unitsTemp.location_id = temp.value("location_id").toString();
unitsTemp.billing_id = temp.value("billing_id").toString();
unitsTemp.created_at = temp.value("created_at").toString();
unitsTemp.update_at = temp.value("update_at").toString();
unitsTemp.nickname = temp.value("nickname").toString();
unitsTemp.image = temp.value("image").toString();
unitsTemp.status = temp.value("status").toString();
unitsTemp.ac_role_name = temp.value("ac_role_name").toString();
//QJsonValue siteValue = temp.value("location").toArray();
//QJsonObject locationObject = siteValue.toObject();
//How to get location data ?
QJsonArray dataObjectz = temp.value("location").toArray().at(0).toArray();
//unitsTemp.locations.address = locationObject.value("address").toString();
//devo prendere le location
QString debug;
}
return lista;
}
I've tried code and codes...but how to get location data ?? I don't found the solution works for me.
Any idea ?
I'm new in qt and c++. thanks.
The solutions it's:
QJsonObject locationObject = temp["location"].toObject();
QString addressFromLocation = locationObject.value("address").toString();
work for me

Adding attachment to JIRA issue using the REST API and Qt with QNetworkRequest

I'm trying to add an attacment to an existing JIRA issue using the REST API and Qt.
When I run the code below, the reply is an empty array ("[]").
edit: updated the code
QString APIhandler::attachFile(QString fileloc, QString issueKey, QString cookie)
{
//create multiPart
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QFile *file = new QFile(fileloc);
//create httpPart for file
QHttpPart filePart;
filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));
filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\"; filename=\""+ file->fileName()+ "\""));
file->open(QIODevice::ReadOnly);
filePart.setBodyDevice(file);
file->setParent(multiPart);
multiPart->append(filePart);
QNetworkAccessManager *mngr = new QNetworkAccessManager();
QUrl issurl(baseURL + "/api/2/issue/"+ issueKey + "/attachments");
QNetworkRequest req(issurl);
QNetworkReply *reply ;
QEventLoop loop;
//add headers
req.setRawHeader("cookie", "JSESSIONID = " + cookie.toUtf8()); // the session cookie
req.setRawHeader("X-Atlassian-Token", "nocheck");
req.setRawHeader("Content-Type", "multipart/form-data; boundary=------------------------53a5a2cd1d9c8b7f");
//req.setRawHeader("Content-Length", postDataSize);
reply = mngr->post(req, multiPart);
multiPart->setParent(reply);
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
return reply->readAll();
}
I am using the JIRA REST API documentation and qt documentation for reference, and looking off of this java implementation (which I've tried to replicate).
It seems like I'm either missing a header, or adding the file incorrectly.
Any help is greatly appreciated!
EDIT - Here's part of a wireshark comparing the example from the api using curl (LEFT) , and my code (RIGHT). The one on the left works, and clearly has different MIME data, but I'm not sure how to implement that in Qt
Okay, so I figured it out. I might be the only one on earth who is using (or will use) Qt to interact with the JIRA API, but for posterity, here's what I came up with:
QString APIhandler::attachFile(QString fileloc, QString issueKey, QString cookie)
{
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart filePart;
QFileInfo fileInfo(fileloc);
//what I wasn't doing before!
multiPart->setBoundary("------------------------53a5a2cf4d9c8b7f");
filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\"; filename=\""+fileInfo.fileName() +"\""));
filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));
QFile *file = new QFile(fileloc);
file->open(QIODevice::ReadOnly);
filePart.setBodyDevice(file);
file->setParent(multiPart);
multiPart->append(filePart);
QNetworkAccessManager *mngr = new QNetworkAccessManager();
QUrl issurl(baseURL + "/api/2/issue/"+ issueKey + "/attachments");
QNetworkRequest req(issurl);
QNetworkReply *reply ;
QEventLoop loop;
//add headers
req.setRawHeader("X-Atlassian-Token", "nocheck");
req.setRawHeader("cookie", "JSESSIONID = " + cookie.toUtf8()); // the session cookie
req.setRawHeader("Content-Type", "multipart/form-data;boundary=------------------------53a5a2cf4d9c8b7f");
reply = mngr->post(req, multiPart);
multiPart->setParent(reply);
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
//read the reply
QByteArray bytes=reply->readAll();
//return the reply JSON
return QString::fromUtf8(bytes.data(), bytes.size());
delete file;
delete multiPart;
delete reply;
delete mngr;
}
The key part here, and what I was doing wrong, was the way in which I set the boundary for the multipart. Instead of setting it in the header, I should have used:
multipart->setBoundary()
Which you can see reflected above.
If you're coming across this and are going to use it, I'd recommend cleaning it up a bit, first. But it works!

How to intercept AJAX-Requests within QtWebKit?

I want to intercept, inspect and (if needed) reject AJAX-Requests based on the Fingerprint of the SSL-Certificate. I use the QNetworkAccessManager::createRequest(...) function to issue requests. Everything works fine when I use QWebFrame::load(...). Even the content which is loaded within the request (like .css or .js files) emit signals. Unfortunately no AJAX-Requests emits any Signals. I know that the Signals are connected to the very same slots (for "normal" as well as AJAX-Requests) within MyNetworkAccessManager::createRequest(...) function.
QNetworkReply *reply = QNetworkAccessManager::createRequest(op, req, outgoingData);
connect(reply, SIGNAL(readyRead()), this, SLOT(handleStarted()));
connect(reply, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(handleSslErrors(const QList<QSslError> &)));
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(handleNetworkError()));
Why are AJAX Requests so different? Where can I access them?
From what I can tell, AJAX requests do emit the finished signal on QNetworkAccessManager. You need connect to the instance of QNetworkAccessManager on your QWebPage instance:
QWebPage *page = ui->webView->page();
QNetworkAccessManager *nam = page->networkAccessManager();
connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
QFile file;
file.setFileName(":/js/jquery-2.1.1.min.js"); // jQuery is loaded as a resource
file.open(QIODevice::ReadOnly);
QString jQuery = file.readAll();
file.close();
ui->webView->load(QUrl("about:blank"));
QWebFrame *frame = m_page->mainFrame();
frame->evaluateJavaScript(jQuery); // load jQuery
// check that jQuery is loaded
frame->evaluateJavaScript("$(document).ready(function() { alert('jQuery loaded!'); });");
// do an AJAX GET
frame->evaluateJavaScript("$.ajax({"
"url: 'http://www.json-generator.com/api/json/get/cqkXBAEoQy?indent=2',"
"method: 'GET',"
"dataType: 'json'"
"}).done(function (data) {"
"for (var i = 0; i < data.length; i++) {"
"alert(data[i].name);"
"}"
"}).error(function (data) { alert('AJAX error'); });");
Then you can monitor replies in the replyFinished slot like so:
void MainWindow::replyFinished(QNetworkReply *reply)
{
QByteArray bytes = reply->readAll();
QString str = QString::fromUtf8(bytes.data(), bytes.size());
QString replyUrl = reply->url().toString();
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
qDebug() << statusCode;
qDebug() << replyUrl;
qDebug() << str;
}
I have noticed that jQuery AJAX's done promise doesn't seem to execute when you do anything with the QNetworkReply, but you can see that the request actually finishes in the debug console.
See my GitHub repository to try out the above code: https://github.com/pcmantinker/QtWebkitAJAX
As far as blocking connections based on SSL certificates, you'd have to subclass QNetworkAccessManager and override QNetworkAccessManager::createRequest. Something like this could work:
QNetworkReply *CustomQNetworkAccessManager::createRequest(Operation op, const QNetworkRequest& request, QIODevice* outgoingData)
{
QNetworkRequest req(request);
QNetworkReply *reply = QNetworkAccessManager::createRequest(op, req, outgoingData);
QSslConfiguration *sslConfig = reply->sslConfiguration();
QList<QSslCertificate> sslCaCerts = sslConfig->caCertificates();
// do something with sslCaCerts
return reply;
}