How can I get qjsonvalue to string? - c++

What should i do to get output for example: Bid value is 2248.48?
Here is code:
QNetworkRequest request = QNetworkRequest(QUrl("https://api.30.bossa.pl/API/GPW/v2/Q/C/_cat_name/WIG20?_t=1637005413888"));
QNetworkReply* reply = m_manager.get(request);
QObject::connect(reply, &QNetworkReply::finished, [reply]() {
QByteArray rawData = reply->readAll();
QString textData(rawData);
// qDebug() << textData;
QJsonDocument doc = QJsonDocument::fromJson(textData.toUtf8());
auto rootObj = doc.object();
auto _d = rootObj.value("_d").toArray();
auto _t = _d[0].toObject().value("_t").toArray();
auto _quote = _t[0].toObject().value(QString("_quote"));
qDebug() << _quote;
eply->deleteLater();
Now i get QJsonValue (string, "2248.48)
when i tried this:
QJsonObject root = _t[0].toObject().value(QString("_quote"));
qDebug() << root;
QJsonValue value = obj.value(QString("_quote"));
qDebug() << "Bid value is" << value.toString();;
https://api.30.bossa.pl/API/GPW/v2/Q/C/_cat_name/WIG20?_t=1637005413888
{"message":"OK","_quote_date":null,"_type":"C","_symbol":["WIG20"],"_d":[{"_h":"Własne - 22 listopada 2021 16:42","_hs":"Własne","_max_quote_dtm":"22 listopada 2021","_max_quote_dtm_lc":"22 listopada, 16:42","_ret_quote_dtm":"2021-11-22","_t":[{"_symbol":"WIG20","_symbol_short":"WIG20","_group":"X1","_isin":"PL9999999987","_quote_date":"2021.11.22","_quote_time":"16:42","_time":"16:42","_phase":"Sesja","_quote_max":"2262.74","_quote_min":"2237.64","_quote_open":"2251.08","_quote_ref":"2248.18","_quote_imp":"2254.37","_bid_size":null,"_bid_volume":null,"_bid_orders_nr":null,"_ask_size":null,"_ask_volume":null,"_ask_orders_nr":null,"_volume":null,"_open_positions":null,"_quote_volume":null,"_transactions_nr":null,"_turnover_value":841977698,"_quote":"2254.10","_step":"2","_type_of_instrument":"0","_settlement_price":null,"_change_proc":0.26,"_change_pnts":5.9200,"_30d_change_max":2449.6400,"_30d_change_min":2221.6800,"_change_type":"_change_proc","_quote_type":"_quote","_debut":"0","_live":"1","_sw_symbol_short":0,"_is_indice":"1","_change":"+0.26","_change_suffix":"%","_change_max_min":"+1.12","_change_close_open":"+0.13","_change_settl_ref":null}]}],"_i":[null],"_count":1,"_d_fx":{"_h":null,"_hs":null,"_max_quote_dtm":null,"_max_quote_dtm_lc":null,"_t":[]}}
I got erros "QJsonValue to non-scalar type QJsonObject requested"

You either want _quote.toString() (first listing) or root.toString() (second listing)

Related

AWS execute API request using QT 5

i am trying to create an API request to an AWS API, right now i fix the first issue that is related to generate de signature version 4, but no matter what i do, AWS response tell me that the signature is not welll generated, i already check the signature using nodejs code and works, according what i see and what AWS SUpport say, it is possible that some request headers are missing.
I am adding my QT Code i know that is not the best but is only an example, the function that i using to make the post request is loginWekall
#include "hash.h"
#include <QDateTime>
#include <QJsonObject>
#include <QJsonDocument>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QBuffer>
#include <QNetworkReply>
CryptoHash::CryptoHash(QObject *parent) : QObject(parent)
{
}
QString CryptoHash::getKey(){
return this->key;
}
void CryptoHash::setKey(QString key){
this->key = key;
}
void CryptoHash::setSecret(QString secret){
this->secret = secret;
}
void CryptoHash::setRegion(QString region){
this->region = region;
}
void CryptoHash::setMethod(QString method){
this->method = method;
}
void CryptoHash::setEndpoint(QString endpoint){
this->endpoint = endpoint;
}
void CryptoHash::setHost(QString host){
this->host = host;
}
void CryptoHash::setURL(QString URL){
this->url = URL;
}
QString CryptoHash::getHash() {
return this->hashvalue;
}
const QByteArray CryptoHash::getSignatureKey(QString datestamp) {
QMessageAuthenticationCode code(QCryptographicHash::Sha256);
code.setKey(datestamp.toUtf8());
code.addData("AWS4" + this->key.toUtf8());
QByteArray kDate = code.result();
code.reset();
code.setKey(this->region.toUtf8());
code.addData(kDate);
QByteArray kRegion = code.result();
code.reset();
code.setKey(this->service.toUtf8());
code.addData(kRegion);
QByteArray kService = code.result();
code.reset();
code.setKey("aws4_request");
code.addData(kService);
const QByteArray kSignin = code.result();
return kSignin;
}
QByteArray CryptoHash::algorithmDesignation(const QCryptographicHash::Algorithm algorithm) {
switch (algorithm) {
case QCryptographicHash::Md4: return "AWS4-HMAC-MD4";
case QCryptographicHash::Md5: return "AWS4-HMAC-MD5";
case QCryptographicHash::Sha1: return "AWS4-HMAC-SHA1";
case QCryptographicHash::Sha224: return "AWS4-HMAC-SHA224";
case QCryptographicHash::Sha256: return "AWS4-HMAC-SHA256";
case QCryptographicHash::Sha384: return "AWS4-HMAC-SHA384";
case QCryptographicHash::Sha512: return "AWS4-HMAC-SHA512";
default:
Q_ASSERT_X(false, Q_FUNC_INFO, "invalid algorithm");
return "invalid-algorithm";
}
}
QByteArray CryptoHash::canonicalHeader(const QByteArray &headerName, const QByteArray &headerValue) {
QByteArray header = headerName.toLower() + ':';
const QByteArray trimmedHeaderValue = headerValue.trimmed();
bool isInQuotes = false;
char previousChar = '\0';
for (int index = 0; index < trimmedHeaderValue.size(); ++index) {
char thisChar = trimmedHeaderValue.at(index);
header += thisChar;
if (isInQuotes) {
if ((thisChar == '"') && (previousChar != '\\'))
isInQuotes = false;
} else {
if ((thisChar == '"') && (previousChar != '\\')) {
isInQuotes = true;
} else if (isspace(thisChar)) {
while ((index < trimmedHeaderValue.size()-1) &&
(isspace(trimmedHeaderValue.at(index+1))))
++index;
}
}
previousChar = thisChar;
}
return header;
}
QByteArray CryptoHash::canonicalHeaders(const QNetworkRequest &request, QByteArray * const signedHeaders) {
Q_CHECK_PTR(signedHeaders);
signedHeaders->clear();
QMap<QByteArray,QByteArray> headers;
foreach (const QByteArray &rawHeader, request.rawHeaderList()) {
headers.insert(rawHeader.toLower(), request.rawHeader(rawHeader));
}
headers.insert("host", request.url().host().toUtf8());
headers.insert("x-amz-date", this->amz.toUtf8());
QByteArray canonicalHeaders;
for (QMap<QByteArray,QByteArray>::const_iterator iter = headers.constBegin(); iter != headers.constEnd(); ++iter) {
canonicalHeaders += canonicalHeader(iter.key(), iter.value()) + '\n';
if (!signedHeaders->isEmpty()) *signedHeaders += ';';
*signedHeaders += iter.key();
}
return canonicalHeaders;
}
QByteArray CryptoHash::canonicalRequest(const QNetworkAccessManager::Operation operation,
const QNetworkRequest &request,
const QByteArray &payload,
QByteArray * const signedHeaders) {
//qInfo() <<"payload";
//qInfo() << payload;
//qInfo() << QCryptographicHash::hash(payload, QCryptographicHash::Sha256).toHex();
return this->method.toUtf8() + '\n' +
this->endpoint.toUtf8() + '\n' +
"\n" + canonicalHeaders(request, signedHeaders) + '\n' +
*signedHeaders + '\n' +
QCryptographicHash::hash(payload, QCryptographicHash::Sha256).toHex();
}
QByteArray CryptoHash::credentialScope(const QDateTime &date, const QString &region, const QString &service) {
return this->dstamp.toUtf8() + '/' + region.toUtf8() + '/' + service.toUtf8() + "/aws4_request";
}
QByteArray CryptoHash::stringToSign(const QByteArray &algorithmDesignation, const QString &requestDate,
const QByteArray &credentialScope, const QByteArray &canonicalRequest) {
return algorithmDesignation + '\n' +
this->amz.toUtf8() + '\n' +
credentialScope + '\n' +
QCryptographicHash::hash(canonicalRequest, QCryptographicHash::Sha256).toHex();
}
QByteArray CryptoHash::signingKey( const QDate &date,
const QString &region, const QString &service) {
const QCryptographicHash::Algorithm hashAlgorithm = QCryptographicHash::Sha256;
return QMessageAuthenticationCode::hash("aws4_request",
QMessageAuthenticationCode::hash(service.toUtf8(),
QMessageAuthenticationCode::hash(region.toUtf8(),
QMessageAuthenticationCode::hash(this->dstamp.toUtf8(), "AWS4"+this->secret.toUtf8(),
hashAlgorithm), hashAlgorithm), hashAlgorithm), hashAlgorithm);
}
void debugRequest(QNetworkRequest request, QByteArray data = QByteArray())
{
qDebug() << request.url().toString();
const QList<QByteArray>& rawHeaderList(request.rawHeaderList());
foreach (QByteArray rawHeader, rawHeaderList) {
qDebug() << request.rawHeader(rawHeader);
}
qDebug() << data;
}
QString CryptoHash::loginWekall(const QString AWSV4, const QString timestamp){
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
QUrl url("https://asdasdasd.execute-api.us-east-1.amazonaws.com/master/users/login");
QNetworkRequest request(url);
QJsonObject obj;
obj["email"] = "user#test.co";
obj["password"] = "password";
QJsonDocument doc(obj);
QByteArray data = doc.toJson();
// FIXME for debug
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader("Content-Type", "application/json");
request.setRawHeader("Authorization", AWSV4.toUtf8());
request.setRawHeader("X-Amz-Date", this->amz.toUtf8());
request.setRawHeader("Host","g298zqijvh.execute-api.us-east-1.amazonaws.com");
request.setRawHeader("Accept","application/json, text/plain, */*");
qDebug() << request.url().toString();
const QList<QByteArray>& rawHeaderList(request.rawHeaderList());
foreach (QByteArray rawHeader, rawHeaderList) {
qDebug() << request.rawHeader(rawHeader);
}
qDebug() << data;
QNetworkReply *reply = manager->post(request, data);
QObject::connect(reply, &QNetworkReply::finished, [=](){
if(reply->error() == QNetworkReply::NoError){
QString contents = QString::fromUtf8(reply->readAll());
qDebug() << contents;
}
else{
qInfo()<< QString::fromUtf8(reply->readAll());
QString err = reply->errorString();
qDebug() << err;
}
reply->deleteLater();
});
return "true";
}
QString CryptoHash::getDate(){
return this->amz;
}
QString CryptoHash::hash(){
const QDateTime datetime;
QDateTime* dtime = new QDateTime();
QString amzdate = dtime->currentDateTimeUtc().toString("yyyyMMddThhmmssZ").toUtf8();
QString datestamp = dtime->currentDateTimeUtc().toString("yyyyMMdd").toUtf8();
QJsonObject data;
this->amz = amzdate;
//this->amz = "20210306T142037Z";
this->dstamp = datestamp;
qInfo() <<"amztime";
qInfo() << amzdate;
qInfo() <<"date";
qInfo() << datestamp;
data["email"] = "user#test.co";
data["password"] = "password";
QJsonDocument doc(data);
QByteArray strData(doc.toJson(QJsonDocument::Compact));
qInfo() << "JSON parameters";
qInfo() << strData;
const QByteArray algorithmDesignation = this->algorithmDesignation(QCryptographicHash::Sha256);
const QString endpoint = this->endpoint;
QString signa = "host;x-amz-date";;
const QByteArray credentialScope = this->credentialScope(datetime, this->region, this->service);
QString access = "ACCESSKEYID/";
this->scope = access.toUtf8() + this->dstamp+ "/us-east-1/execute-api/aws4_request";
qInfo() << "credentialScope";
qInfo() << credentialScope;
QByteArray signedHeaders = signa.toUtf8();
qInfo() << "signedHeaders";
qInfo() << signedHeaders;
const QUrl URL("https://asdasd.execute-api.us-east-1.amazonaws.com/master/users/login");
const QNetworkRequest request(URL);
const QByteArray canonicalRequest = this->canonicalRequest(QNetworkAccessManager::Operation::PostOperation, request, strData, &signedHeaders);
qInfo() << "canonical request";
qInfo() << canonicalRequest;
const QByteArray stringToSign = this->stringToSign(algorithmDesignation, this->amz, credentialScope, canonicalRequest);
qInfo() << "stringToSign";
qInfo() << stringToSign;
const QByteArray signingKey = this->signingKey(datetime.date(), this->region, this->service);
qInfo() << "signinKey";
qInfo() << signingKey;
const QByteArray signature = QMessageAuthenticationCode::hash(stringToSign, signingKey, QCryptographicHash::Sha256);
qInfo() << "signature";
qInfo() << signature;
this->hashvalue = algorithmDesignation + " Credential=" + this->key.toUtf8() + '/' + credentialScope +
", SignedHeaders=" + signedHeaders + ", Signature=" + signature.toHex();
qInfo() << "AWS SIGNATURE VERSION 4";
qInfo() << this->hashvalue;
this->loginWekall(hashvalue, this->amz);
return 0;
}
CryptoHash::~CryptoHash(){};

QT: How to replace number (Start, End) in a JSON from server

This is how my JSON file looks like. As you can see, the start_x, start_y, and end_x, end_y, degree_of_rotation is a number.
{
"ID" : "ROLL1",
"action" : "start",
"zone" :
{
"start_x" : 0,
"start_y" : 4,
"end_x" : 10,
"end_y" : 5,
"motion" :
{
"motion_type": "xxxxxx",
"degree_of_rotation": 30,
"rotation_direction": "yyyyyy",
"linear_direction": "+ve"
}
}
}
How can I replace and save the number in JSON from the server? Currently, this is what I have. Qt5 has a new JSON parser and I want to use it. The problem is that it isn't too clear about what the functions do
void JsonFileread::Json_File_Function()
{
try
{
qDebug() <<"file reading";
file.setFileName("/home/JSON/jsonfile.js");
file.open(QIODevice::ReadOnly | QIODevice::Text);
QFileDevice::FileError err = QFileDevice::NoError;
if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
qDebug() <<"Could not open file : "<<file.fileName() <<"for reading :"<<file.errorString()<<endl;
errMsg =file.errorString();
err =file.error();
cout<<"err : "<<err<<endl;
}
settings = file.readAll();
if (file.error() != QFile::NoError) {
qDebug() << QString("Failed to read from file %1, error: %2").arg(file.fileName()).arg(file.errorString());
}
if (settings.isEmpty()) {
qDebug() << "No data was currently available for reading from file" << file.fileName();
}
file.close();
object = EchoClient::jsonstringflag;
QJsonDocument sd = QJsonDocument::fromJson(settings.toUtf8());
QJsonObject sett2 = sd.object();
QJsonValue mainid = sett2["ID"];
mainid = mainid.toString();
QJsonValue action = sett2["action"];
actionstring = action.toString();
QJsonValue value = sett2.value(QString("zone"));
QJsonObject item = value.toObject();
QJsonValue startx = item["start_x"];
startvaluex = startx.toInt();
QJsonValue starty = item["start_y"];
startvaluey = starty.toInt();
QJsonValue endx = item["end_x"];
endvaluex = endx.toInt();
xendvaluestring = endx.toString();
qWarning() << endvaluex<<endl;
QJsonValue endy = item["end_y"];
endvaluey = endy.toInt();
yendvaluestring = endy.toString();
qWarning() << endvaluey<<endl;
QJsonValue motion = item.value(QString("motion"));
QJsonObject motion_object = motion.toObject();
QJsonValue motiontype = motion_object["motion_type"];
motiontypestring = motiontype.toString();
QJsonValue directionlinear = motion_object["linear_direction"];
lineardirection = directionlinear.toString();
QJsonValue rotatingangle = motion_object["degree_of_rotation"];
angleofrotation = rotatingangle.toInt();
}
catch (QJsonParseError error)
{
qDebug() << error.errorString();
}
catch(...)
{
qDebug() << "due to some other error";
}
}
So help to solve the problem
You can write to a QJsonObject very similar to how you read its properties
QJsonObject obj;
obj["key"] = value;
Once you have built the QJsonObject tree, set the top level element on a QJsonDocument and use it to generate the JSON content.

i have made changes to the code

this is my method and it does not work.
void ApplicationUI::Post(const QString &id,const QString &name,const QString &surname,const QString &grade, const QString &dob,const QString &language,const QString &school, const QString &gender,const QString &cellno,const QString &registrationDate)
{
this->connection = new QNetworkAccessManager(this);
connect(this->connection, SIGNAL(finished(QNetworkReply*)), this, SLOT(postFinished()));
QUrl url("http://172.27.15.7/BB10_Scripts/Registration.php");
QUrl postParams;
postParams.addQueryItem("id",id);
postParams.addQueryItem("name", name);
postParams.addQueryItem("surname",surname);
postParams.addQueryItem("grade",grade);
postParams.addQueryItem("dob",dob);
postParams.addQueryItem("language",language);
postParams.addQueryItem("school",school);
postParams.addQueryItem("gender",gender);
postParams.addQueryItem("cellno",cellno);
postParams.addQueryItem("registrationDate",registrationDate);
QByteArray data;
data.append(postParams.data);
data.remove(0,1);
QNetworkRequest req;
req.setUrl(url);
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
this->connection->post(req,postParams.encodedQuery());());
bool ok = QObject::connect(connection, SIGNAL(finished(QNetworkReply*)), this, SLOT(postFinished()));
Q_ASSERT(ok);
Q_UNUSED(ok);
qDebug() << "Connection is success : ? : " << ok;
}
i get the message
Connection is success : ? : true
Process 476930267 (CascadesProject) terminated SIGSEGV code=1 fltno=11 >ip=79f70ce2 >(/base/usr/lib/qt4/lib/libQtNetwork.so.4.8.5#_ZNK13QNetworkReply5errorEv+0x9) >mapaddr=00060ce2. ref=00000004 bdslot=1
postParams.addQueryItem("id", id);
postParams.addQueryItem("name", name);
postParams.addQueryItem("surname", surname);
postParams.addQueryItem("grade", grade);
postParams.addQueryItem("dob", dob);
postParams.addQueryItem("language", language);
postParams.addQueryItem("school", school);
postParams.addQueryItem("gender", gender);
postParams.addQueryItem("cellno", cellno);
postParams.addQueryItem("registrationDate",registrationDate);
QNetworkRequest request;
request.setUrl(QUrl("http://172.27.15.7/BB10_Scripts/Registration.php?"));
bool res;
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
Q_UNUSED(res);
this->reply = connection->post(request, postParams.encodedQuery());
res = QObject::connect(this->reply, SIGNAL(finished()),this, SLOT(postFinished()));
Q_ASSERT(res);
Q_UNUSED(res);
qDebug() << "Connection is success : ? : " << res;

Get Image URL From String

I am trying to figure out a way to get a image url from a web page source.
I can get the web page source into a string and parse it line by line to find the line with the URL.
However, I haven't been able to figure out a good way to pull just the URL from the line.
I'm think this can be done with QRegExp, but have been unable to figure out how to use it.
Line I am trying to parse
<img width="980" height="1515" id="mainImg" src="//test/123.jpg" alt="test">
Final Working Code
void MainWindow::on_btnDownload_clicked()
{
QString url = "http://test.foo.com";
QUrl qURL = url;
QNetworkAccessManager manager;
QNetworkReply *response = manager.get(QNetworkRequest(QUrl(url)));
QEventLoop event;
connect(response,SIGNAL(finished()),&event,SLOT(quit()));
event.exec();
QString html = response->readAll();
QStringList str;
str = html.split("\n");
//qDebug() << url;
for (int i = 0; i < str.size(); ++i){
if(str.at(i).contains("id=\"mainImg\"", Qt::CaseInsensitive)){
QString pic;
pic = str.at(i);
pic = pic.remove(QRegExp("<img[^>]*src=['|\"]", Qt::CaseInsensitive));
pic = pic.remove(QString::fromStdString("//"), Qt::CaseInsensitive);
pic = pic.remove('"');
pic = pic.remove("'");
pic = pic.remove('<');
pic = pic.remove('>');
pic = pic.remove(';');
pic = pic.left(pic.length()-1);
//qDebug() << str.at(i);
qDebug() << pic;
}
}
qDebug() << "Lines: " << str.size();
}

Proper way to handle multiple QNetworkRequests

im grabbing url's from a list and then sending each to a QNetworkRequest and recieving the HTML back to process. I however have thousands of requests to process. So my application kept hanging until i stopped it from producing all these requests at once.
Is this the rite way to handle the que for a great number of requests?
I tried using a Qqueue of Urls, which i would then link to a SLOT which was triggered after each QNetworkReply reponse.
Create the job list and add to que
QQueue<QString> jobs;
for (int i = 1; i <= totalPages; i++){
QString pageUrl = url + "&page=" + QString::number(i);
jobs.enqueue(pageUrl);
}
qDebug() << "Total Jobs : " << jobs.count() << endl;
for (int i = 0; i < 5; i++){
processQueue();
}
then inside the getHtml function
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
QNetworkRequest *getHtmlRequest = new QNetworkRequest(pageUrl);
getHtmlRequest = new QNetworkRequest(url);
getHtmlRequest->setRawHeader( "User-Agent", "Mozilla/5.0 (X11; U; Linux i686 (x86_64); "
"en-US; rv:1.9.0.1) Gecko/2008070206 Firefox/3.0.1" );
getHtmlRequest->setRawHeader( "charset", "utf-8" );
getHtmlRequest->setRawHeader( "Connection", "keep-alive" );
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyGetPageHtmlFinished(QNetworkReply*)));
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(processQueue()));
manager->get(*getHtmlRequest);
which triggers
void checkNewArrivalWorker::processQueue(){
if (jobs.isEmpty()){
qDebug() << "Jobs Completed" << endl;
emit finished();
} else {
QString pageUrl = jobs.dequeue();
QString pageNumber = pageUrl.mid(pageUrl.indexOf("page=") + 5);
getHtml(pageUrl, pageNumber);
}
}