I am wondering how I would foreach through a QJsonObject to get the key/value pairs in C++? So far, I am only able to get the value.
//main.cpp
QFile file(":/geoip.json");
file.open(QIODevice::ReadOnly);
QByteArray rawData = file.readAll();
file.close();
QJsonDocument doc(QJsonDocument::fromJson(rawData));
QJsonObject json = doc.object();
foreach(const QJsonValue &value, json) {
QJsonObject obj = value.toObject();
qDebug() << value;
}
//geoip.json
{
"Afghanistan": "58.147.159.255",
"Albania": "31.22.63.255",
"Algeria": "105.235.143.255",
"American Samoa": "202.70.115.241",
"Andorra": "109.111.127.255",
"Angola": "105.175.255.255",
"Anguilla": "208.66.50.44",
"Antarctica": "46.36.195.10"
}
John already gave the answer. Using keys() a complete working solution would be:
#include <QCoreApplication>
#include <QFile>
#include <QByteArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//main.cpp
QFile file("path/to/geoip.json");
file.open(QIODevice::ReadOnly);
QByteArray rawData = file.readAll();
file.close();
QJsonDocument doc(QJsonDocument::fromJson(rawData));
QJsonObject json = doc.object();
foreach(const QString& key, json.keys()) {
QJsonValue value = json.value(key);
qDebug() << "Key = " << key << ", Value = " << value.toString();
}
return a.exec();
}
I know this post is old but to answer Nuclear
With the method proposed by Twisq it is possible to browse a JSON by obtaining the keys and values without problem.
But you are talking about iterating a JSON...?
With "QJsonObject::const_iterator" objects it is possible with the code below:
#include<QJsonDocument>
#include<QJsonObject>
#include<QFile>
int main (int nbArg, char* listArg[])
{
QFile file("my_file.json");
file.open(QIODevice::ReadOnly);
QByteArray rawData = file.readAll();
file.close();
QJsonDocument doc(QJsonDocument::fromJson(rawData));
QJsonObject myJson = doc.object();
QJsonObject::const_iterator myIterator = myJson.constBegin();
QJsonObject::const_iterator myIteratorEnd = myJson.constEnd();
do
{
qDebug() << myIterator.key();
qDebug() << myIterator.value();
myIterator++;
}
while(myIterator!=myIteratorEnd);
}
Related
I have a "cell" class that describes some kind of smart device. I've got plenty of them. Each of these devices must implement a connection to the server. I have written methods in the "cell" class.
cell.cpp
#include "cell.h"
#include <QDateTime>
#include <QMessageBox>
cell::cell(QObject *parent) : QObject(parent)
{
}
void cell::Connect(){
m_client = new QMqttClient(this);
m_client->setHostname("192.111.11.111");
m_client->setPort(1883);
m_client->connectToHost();
QObject::connect(m_client, &QMqttClient::stateChanged, this, &cell::updateLogStateChange);
QObject::connect(m_client, &QMqttClient::disconnected, this, &cell::brokerDisconnected);
}
void cell::MsgReceive(){
connect(m_client, &QMqttClient::messageReceived, this, [this](const QByteArray &message, const QMqttTopicName &topic) {
const QString content =
QLatin1String(" Received Topic: ")
+ topic.name()
+ QLatin1String(" Message: ")
+ message
+ QLatin1Char('\n');
setMsg(content);
});
}
void cell::Publish()
{
QString topic = "topic/";
QString msg = "HELLO";
m_client->publish(topic, msg.toUtf8());
}
void cell::Subscribe()
{
QString topic = "topic/";
auto subscription = m_client->subscribe(topic);
if (!subscription) {
return;
}
}
void cell::updateLogStateChange()
{
const QString content = QDateTime::currentDateTime().toString()
+ QLatin1String(": State Change")
+ QString::number(m_client->state())
+ QLatin1Char('\n');
setLogState(content);
}
void cell::brokerDisconnected()
{
}
In the main window, I create objects through a loop and call the connection methods as an example, just to get a message in the ListWidget.
But it doesn't show up, what's the problem? I would be very grateful if you help me. I just started learning c++.
MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDateTime>
#include <QMessageBox>
#include <modelcell.h>
#include <cell.h>
#include <QThread>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QVector <cell *> listcell;
QString val;
QFile file;
file.setFileName("C:\\Users\\User\\Desktop\\cell.json");
file.open(QIODevice::ReadOnly | QIODevice::Text);
val = file.readAll();
file.close();
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(val.toUtf8(), &error);
if (doc.isObject())
{
QJsonObject json = doc.object();
QJsonArray jsonArray = json["cell"].toArray();
foreach (const QJsonValue & value, jsonArray)
{
if (value.isObject())
{
QJsonObject obj = value.toObject();
QString id = obj["ID"].toString();
QString name = obj["Name"].toString();
QString IP = obj["IP"].toString();
QString status = obj["status"].toString();
cell * cell_obj = new cell;
cell_obj->setName(name);
cell_obj->setID(id);
cell_obj->setIP(IP);
cell_obj->setStatus(status);
cell_obj->Connect();
cell_obj->MsgReceive();
cell_obj->Subscribe();
cell_obj->Publish();
listcell.append(cell_obj);
}
}
}
for(int i = 0; i < listcell.size(); i++){
ui->listWidget->addItem(listcell[i]->getName() + " | " + listcell[i]->getID() + " | " + listcell[i]->getIP()+ " | " + listcell[i]->getStatus());
ui->listWidget->addItem(listcell[i]->getMsg());
}
}
MainWindow::~MainWindow()
{
delete ui;
}
I want the listWidget to display a "hello" message from each created object. But it doesn't happen. Where is the mistake?
I am working with a team on a C++ project using Qt. As part of our project, we have to be able to retrieve coordinates of any given address in France. The French government provivdes an API that handles that for us.
The call to the API looks like this:
curl -X POST -F data=#path/to/file.csv https://api-adresse.data.gouv.fr/search/csv/
Here is the code I wrote:
int main (int argc, char* argv[]){
QCoreApplication app(argc, argv);
QNetworkAccessManager man;
QUrl url("https://api-adresse.data.gouv.fr/search/csv/");
QNetworkRequest req(url);
QFile inputFile("<path_to_search.csv>");
inputFile.open(QIODevice::ReadOnly);
QByteArray data = inputFile.readAll();
QNetworkReply* reply = man.post(req, "data=" + data);
QObject::connect(reply, &QNetworkReply::finished, [&](){
QByteArray read = reply->readAll();
std::cout << "Reading Data:" << std::endl;
std::cout << read.toStdString() << std::endl;
reply->close();
reply->deleteLater();
app.quit();
});
return app.exec();
}
The server replies with
{"code":400,"message":"A CSV file must be provided in data field"}
So clearly I am forwarding the form incorrectly. How should I proceed?
To send information through the forms, I don't know the query section, but rather you want to use QHttpMultiPart as I show in this old post. Applying to your case the solution is:
#include <QCoreApplication>
#include <QFile>
#include <QHttpMultiPart>
#include <QNetworkAccessManager>
#include <QNetworkReply>
QHttpMultiPart *buildMultpart(const QVariantMap & data, const QMap<QString, QString> filenames){
QHttpMultiPart *multipart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QVariantMap::const_iterator i_data = data.constBegin();
while (i_data != data.constEnd()) {
QHttpPart postpart;
postpart.setHeader(QNetworkRequest::ContentDispositionHeader, QString("form-data; name=\"%1\"").arg(i_data.key()));
postpart.setBody(i_data.value().toByteArray());
multipart->append(postpart);
++i_data;
}
QMap<QString, QString>::const_iterator i_filenames = filenames.constBegin();
while (i_filenames != filenames.constEnd()) {
QFile *file = new QFile(i_filenames.value());
if(!file->open(QIODevice::ReadOnly)){
delete file;
continue;
}
QHttpPart postpart;
postpart.setHeader(QNetworkRequest::ContentDispositionHeader,
QString("form-data; name=\"%1\"; filename=\"%2\"")
.arg(i_filenames.key(), file->fileName()));
postpart.setBodyDevice(file);
multipart->append(postpart);
file->setParent(multipart);
++i_filenames;
}
return multipart;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QNetworkAccessManager manager;
QNetworkRequest request;
QUrl url("https://api-adresse.data.gouv.fr/search/csv/");
request.setUrl(url);
QMap<QString, QString> filenames;
filenames["data"] = "/path/of/file.csv";
QHttpMultiPart *multipart = buildMultpart({}, filenames);
QNetworkReply *reply = manager.post(request, multipart);
multipart->setParent(reply);
QObject::connect(reply, &QNetworkReply::finished, [reply](){
if(reply->error() == QNetworkReply::NoError){
qDebug().noquote() << reply->readAll();
}
else{
qDebug() << reply->error() << reply->errorString();
}
reply->deleteLater();
QCoreApplication::quit();
});
return a.exec();
}
I managed to write the data to the objects from the file. But I can't output this data to the console.
I already wrote-ListtForLoad.first().getName()
But can't get such access
I attach the full code of my program.
#include <QCoreApplication>
#include <QFile>
#include <QString>
#include <QDebug>
#include <QIODevice>
#include <QLinkedList>
#include <QTextStream>
class items : public QObject {
public:
items(QString name, QString gryp){
this->name = name;
this->gryp = gryp;
};
QString getName() {
return name;
}
QString getGryp() {
return gryp;
}
private:
QString name;
QString gryp;
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QLinkedList<QObject*> ListtForLoad;
QFile fileIn("myfile.txt");
QFile fileOut("myfileout.txt");
int lineCount = 0;
if (fileIn.open(QIODevice::ReadOnly | QIODevice::Text)){
lineCount = QTextStream(&fileIn).readAll().split('\n').count();
fileIn.close();
}
QString stringAllRead;
if(fileIn.open(QIODevice::ReadOnly)) {
stringAllRead = fileIn.readAll();
QStringList splitLines = stringAllRead.split("\r\n");
for (int countItems = 0; countItems < lineCount; countItems++) {
QStringList people = splitLines[countItems].split("&");
ListtForLoad << new items( people[0], people[1] );
}
qDebug() << ListtForLoad.first().getName();
fileOut.close();
}
return a.exec();
}
You are storing QObject*'s in the QLinkedList so when you do the below, you get a QObject* back:
ListtForLoad.first() // <- QObject* here
.getName()
To derefernce a pointer, you need to use -> instead of . so:
ListtForLoad.first()->getName();
However, QObject doesn't have a getName() member function.
You should probably store your own type (items) in the list instead:
QLinkedList<items*> ListtForLoad;
I'm new to Qt Framework and I'm trying to get the list of earthquakes from EMSC api. My code looks like this:
void MainWindow::getJsonData(QNetworkAccessManager *mNetworkManager) {
const QUrl json("https://www.seismicportal.eu/fdsnws/event/1/query?limit=100&format=json");
QNetworkRequest *mNetworkRequest = new QNetworkRequest;
mNetworkRequest->setUrl(json);
mNetworkRequest->setRawHeader("Content-Type", "application/json");
mNetworkRequest->setRawHeader("Accept", "application/json");
QNetworkReply *mNetworkReply = mNetworkManager->get(*mNetworkRequest);
QString replyString = (QString) mNetworkReply->readAll();
QJsonDocument document = QJsonDocument::fromJson(replyString.toUtf8());
QJsonObject object = document.object();
QJsonValue type = object["type"].toString();
QJsonArray featuresArray = object["features"].toArray();
qDebug() << type;
qDebug() << featuresArray;
}
The problem is that I'm not getting any response from the server.
Qt is a library (not a framework) that handles all transactions asynchronously through signals and slots, so don't expect the response to be obtained synchronously.
#include <QCoreApplication>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
class Client: public QObject{
public:
void startRequest(){
const QUrl json("https://www.seismicportal.eu/fdsnws/event/1/query?limit=100&format=json");
QNetworkRequest request;
request.setUrl(json);
request.setRawHeader("Content-Type", "application/json");
request.setRawHeader("Accept", "application/json");
QNetworkReply *reply = mNetworkManager.get(request);
connect(reply, &QNetworkReply::finished, this, &Client::processRequest);
}
private:
void processRequest(){
QNetworkReply * reply = qobject_cast<QNetworkReply *>(sender());
if(!reply) return;
QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
QJsonObject object = document.object();
QJsonValue type = object["type"].toString();
QJsonArray featuresArray = object["features"].toArray();
qDebug() << type << featuresArray;
reply->deleteLater();
}
QNetworkAccessManager mNetworkManager;
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Client client;
client.startRequest();
return a.exec();
}
Output:
QJsonValue(string, "FeatureCollection") QJsonArray([{"geometry":{"coordinates":[16.23,45.4,-2],"type":"Point"},"id":"20210202_0000178", ...
Here's some of my code:
QNetworkRequest req (QUrl(QString::fromStdString(url)));
req.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json");
if (authHeader.length() > 0) {
req.setRawHeader(QByteArray("Authorization"), QByteArray::fromStdString(authHeader));
}
QByteArray bodyArray;
if (body.length() > 0) {
bodyArray.append(QString::fromStdString(body).toUtf8());
}
QNetworkReply * reply = method(req, bodyArray);
QObject::connect(reply, &QNetworkReply::finished, [=]{
.... });
Is there a way to print the data of a QstandardItem out, say I have;
QList<QStandardItem*> testQList;
QString yay = "!Yay";
QStandardItem *item = new QStandardItem(yay);
testQList.append(item);
qDebug() << testQList;
I just get the memory addres, (0x409bd00) I cannot dereference the list either.
You get this because you try to print whole list with objects, it is not list with strings. In this case qDebug always prints memory address so you should use loop and text() method(iterate throw list).
for(int i = 0; i<testQList.size();i++)
{
qDebug() << testQList.at(i)->text();
}
#include <QCoreApplication>
#include <QString>
#include <QList>
#include <QDebug>
class QStandardItem
{
QString mStr;
public:
QStandardItem(QString str)
{
mStr = str;
}
QString toString()
{
return mStr;
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QList<QStandardItem*> testQList;
QString yay = "!Yay";
QStandardItem *item = new QStandardItem(yay);
testQList.append(item);
for(int i = 0; i<testQList.size();i++)
{
qDebug() << testQList.at(i)->toString();
}
return a.exec();
}