Kun Qt-sovelluksessa halutaan käyttää HTTP-protokollaa, on projektiin lisättävä QtNetwork-moduuli seuraavasti:
qmake:
pro-tiedostoon
QT +=network
find_package(Qt6 6.5 REQUIRED COMPONENTS Core Network)
qt_standard_project_setup()
qt_add_executable(projektin_nimi
main.cpp
)
target_link_libraries(projektin_nimi
PRIVATE
Qt::Core
Qt::Network
)
QtNetwork on Qt-kirjaston moduuli, joka tarjoaa kehittäjille työkaluja verkko-ohjelmointiin ja verkkoyhteyksien hallintaan Qt-sovelluksissa. Moduuli sisältää muun muassa seuraavat luokat:
| Luokka | Selite |
|---|---|
| QNetworkAccessManager | QNetworkAccessManager on QtNetwork-moduulin luokka, joka tarjoaa pääsyn verkkoresursseihin ja hallinnoi verkkopyyntöjä. Sen avulla voidaan helposti luoda ja käsitellä HTTP-pyyntöjä ja -vastauksia Qt-sovelluksissa. |
| QNetworkRequest | QNetworkRequest on QtNetwork-moduulin luokka, joka edustaa HTTP- tai muuta verkko-pyyntöä. |
| QNetworkReply | QNetworkReply on QtNetwork-moduulin luokka, josta luodun olion avulla päästään käsiksi http-response dataan. |
| QJsonDocument | QJsonDocument on Qt:n luokka, jota käytetään JSON-objektien ja -taulukoiden (QJsonObject ja QJsonArray) lukemiseen ja kirjoittamiseen. |
| QJsonArray | QJsonArray-luokan avulla voidaan käsitellä JSON-array-tyyppistä dataa. |
| QJsonObject | QJsonObject luokan avulla voidaan käsitellä JSON-object tyyppistä dataa. |
HTTP-responsen data luetaan tämän sivun esimerkeissä QByteArray-luokan olioon.
Huom! Seuraavissa esimerkeissä manager ja reply ovat luokan jäsenmuuttujia. Ne tulee määritellä header-tiedostossa seuraavasti:
private:
QNetworkAccessManager *manager;
QNetworkReply *reply;
Huom! Qt suosittelee, että QNetworkAccessManager luodaan vain kerran sovelluksen elinkaaren aikana, esimerkiksi luokan konstruktorissa.
QString site_url="http://localhost:3000/book"; QNetworkRequest request(site_url); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); //luo manager konstruktorissa manager = new QNetworkAccessManager(this); connect(reply, &QNetworkAccessManager::finished, this, &CurrentClassName::getBookSlot); reply = manager->get(request);Kun HTTP response saapuu, QNetworkAccessManager emittoi finished signaalin, joka on edellä kytketty getBookSlot-slottiin.
QString site_url="http://localhost:3000/book";
QNetworkRequest request(site_url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
//WEBTOKEN ALKU
//Onnistuneen loginin seurauksena saadaan arvo muuttujalle webToken, jonka
//tietotyyppi on QByteArray ja sen eteen asetetaan merkkijono "Bearer "
QByteArray myToken="Bearer "+webToken;
request.setRawHeader(QByteArray("Authorization"),(myToken));
//WEBTOKEN LOPPU
//luo manager konstruktorissa
manager = new QNetworkAccessManager(this);
connect(reply, &QNetworkAccessManager::finished, this, &CurrentClassName::getBookSlot);
reply = manager->get(request);
Huom! Varsinaisen tokenin (eli webToken) eteen on siis kirjoitettava sana Bearer.
Edellä siis tehtiin http-request ja finished-signaali kytkettiin slottiin getBookSlot. Nyt siis response käsitellään tuossa slotissa.
void MainWindow::getBookSlot()
{
// Tarkistetaan verkkovirheet
if (reply->error() != QNetworkReply::NoError) {
qWarning() << "Network error:" << reply->errorString();
reply->deleteLater();
manager->deleteLater();
return;
}
QByteArray response_data=reply->readAll();
// Muunnetaan vastaus QByteArray-tyyppisestä JSON-dokumentiksi
QJsonDocument json_doc = QJsonDocument::fromJson(response_data);
// Muunnetaan JSON-dokumentti JSON-objektiksi
QJsonObject json_obj = json_doc.object();
// Käsitellään JSON-objektia
reply->deleteLater();
manager->deleteLater();
}
void MainWindow::getBookSlot()
{
// Tarkistetaan verkkovirheet
if (reply->error() != QNetworkReply::NoError) {
qWarning() << "Network error:" << reply->errorString();
reply->deleteLater();
manager->deleteLater();
return;
}
QByteArray response_data=reply->readAll();
// Muunnetaan vastaus QByteArray-tyyppisestä JSON-dokumentiksi
QJsonDocument json_doc = QJsonDocument::fromJson(response_data);
// Muunnetaan JSON-dokumentti JSON-arrayksi
QJsonArray json_array = json_doc.array();
// Käsitellään JSON-arraytä
reply->deleteLater();
manager->deleteLater();
}
fromJson metodia, voidaan kutsua myös antamalla QJsonParseError-viite seuraavasti:
QJsonParseError parseError; QJsonDocument json_doc = QJsonDocument::fromJson(response_data, &parseError);Silloin voidaan tarkistaa tapahtuiko virhe seuraavasti:
if (parseError.error != QJsonParseError::NoError) {
qWarning() << "JSON parsing error:" << parseError.errorString();
// Tässä vaiheessa json_doc ei ole kelvollinen
}
JSON-objektin kenttiin päästään käsiksi seuraavasti:
int book_id = json_obj["id_book"].toInt(); QString book_name = json_obj["name"].toString();
JSON-array:tä voidaan käsitellä seuraavalla foreach-loopilla:
foreach (const QJsonValue &value, json_array) {
// Toimenpiteet
}
Jos haluat päästä käsiksi JSON-arrayn yksittäisen objektin kenttään, voit käyttää seuraavaa rakennetta
QString book_name = json_array.at(0)["name"].toString();Edellä QStringiin nimeltään book_name sijoitetaan ensimmäisen objektin (at(0)) name kentän arvo.
Käytännössä JSON-data kannattaa usein mäpätä C++-olioiksi, jolloin sitä on helpompi käsitellä. Esimerkiksi edellisten esimerkkien tapauksessa voisi luoda Book-luokan seuraavilla koodeilla:
#ifndef BOOK_H
#define BOOK_H
#include <qjsonobject.h>
class Book
{
public:
int id;
QString name;
QString author;
static Book mapJson(const QJsonObject &json);
};
#endif // BOOK_H
#include "book.h"
Book Book::mapJson(const QJsonObject &json) {
Book book;
book.id = json["id_book"].toInt();
book.name = json["name"].toString();
book.author = json["author"].toString();
return book;
}
Jos http-responsena saadaan JSON-objekti voidaan luoda Book-luokan olio seuraavasti:
Book book = Book::mapJson(json_obj);
Jos http-responsena saadaan json array voidaan luoda Book-olioita sisältävä QVector seuraavasti:
QVector<Book> bookList;
for (const QJsonValue &value : json_array) {
if (value.isObject()) {
Book book = Book::mapJson(value.toObject());
bookList.append(book);
}
}
Edellä metodi mapJson määriteltiin staattiseksi, jotta: