在Qt5中使用Http Rest客户端请求并解析Json数据
在现代软件开发中,HTTP REST客户端请求是与服务器通信的重要方式之一。在Qt5中,我们可以使用QNetworkAccessManager
类来执行HTTP请求,并使用QSerializer库来解析JSON数据。本文将详细说明如何使用这些工具,并提供GET、POST、PUT、DELETE等请求的示例。
1. 准备工作
首先,我们需要包括必要的头文件,并确保我们的类继承了QObject
。
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QUrlQuery>
#include <QEventLoop>
#include "ReplyData.h"
2. 创建HttpClient类
我们将创建一个HttpClient
类来处理HTTP请求。这个类将包含一个用于发送GET请求的方法。
class HttpClient : public QObject
{
Q_OBJECT
public:
HttpClient(QObject* parent = nullptr) : QObject(parent)
{
}
public:
ReplyData Get(const QString& url)
{
QNetworkAccessManager manager;
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json;charset=utf-8;");
QNetworkReply* reply = manager.get(request);
QEventLoop eloop;
QObject::connect(reply, &QNetworkReply::finished, &eloop, &QEventLoop::quit);
QObject::connect(reply, &QNetworkReply::errorOccurred, &eloop, &QEventLoop::quit);
eloop.exec();
ReplyData data;
if (reply->error() != QNetworkReply::NoError)
{
auto errorString = reply->errorString();
data.code = -2;
data.message = errorString;
reply->deleteLater();
return data;
}
auto jsonStr = reply->readAll();
reply->deleteLater();
if (jsonStr.size() == 0) return data;
data.fromJson(jsonStr);
return data;
}
ReplyData Get(const QUrl& url)
{
QNetworkAccessManager manager;
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json;charset=utf-8;");
QNetworkReply* reply = manager.get(request);
QEventLoop eloop;
QObject::connect(reply, &QNetworkReply::finished, &eloop, &QEventLoop::quit);
QObject::connect(reply, &QNetworkReply::errorOccurred, &eloop, &QEventLoop::quit);
eloop.exec();
ReplyData data;
if (reply->error() != QNetworkReply::NoError)
{
auto errorString = reply->errorString();
data.code = -2;
data.message = errorString;
reply->deleteLater();
return data;
}
auto jsonStr = reply->readAll();
reply->deleteLater();
if (jsonStr.size() == 0) return data;
data.fromJson(jsonStr);
return data;
}
ReplyData Post(const QString& url, const QByteArray& jsonObj)
{
QNetworkAccessManager manager;
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json;charset=utf-8;");
QNetworkReply* reply = manager.post(request, jsonObj);
QEventLoop eloop;
QObject::connect(reply, &QNetworkReply::finished, &eloop, &QEventLoop::quit);
QObject::connect(reply, &QNetworkReply::errorOccurred, &eloop, &QEventLoop::quit);
eloop.exec();
ReplyData data;
if (reply->error() != QNetworkReply::NoError)
{
data.code = -2;
data.message = reply->errorString();
reply->deleteLater();
return data;
}
auto jsonStr = reply->readAll();
reply->deleteLater();
if (!jsonStr.isEmpty())
{
data.fromJson(jsonStr);
}
return data;
}
ReplyData Post(const QUrl& url, const QByteArray& jsonObj)
{
QNetworkAccessManager manager;
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json;charset=utf-8;");
QNetworkReply* reply = manager.post(request, jsonObj);
QEventLoop eloop;
QObject::connect(reply, &QNetworkReply::finished, &eloop, &QEventLoop::quit);
QObject::connect(reply, &QNetworkReply::errorOccurred, &eloop, &QEventLoop::quit);
eloop.exec();
ReplyData data;
if (reply->error() != QNetworkReply::NoError)
{
data.code = -2;
data.message = reply->errorString();
reply->deleteLater();
return data;
}
auto jsonStr = reply->readAll();
reply->deleteLater();
if (!jsonStr.isEmpty())
{
data.fromJson(jsonStr);
}
return data;
}
ReplyData Put(const QString& url, const QByteArray& jsonObj)
{
QNetworkAccessManager manager;
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json;charset=utf-8;");
QNetworkReply* reply = manager.put(request, jsonObj);
QEventLoop eloop;
QObject::connect(reply, &QNetworkReply::finished, &eloop, &QEventLoop::quit);
QObject::connect(reply, &QNetworkReply::errorOccurred, &eloop, &QEventLoop::quit);
eloop.exec();
ReplyData data;
if (reply->error() != QNetworkReply::NoError)
{
data.code = -2;
data.message = reply->errorString();
reply->deleteLater();
return data;
}
auto jsonStr = reply->readAll();
reply->deleteLater();
if (!jsonStr.isEmpty())
{
data.fromJson(jsonStr);
}
return data;
}
ReplyData Put(const QUrl& url, const QByteArray& jsonObj)
{
QNetworkAccessManager manager;
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json;charset=utf-8;");
QNetworkReply* reply = manager.put(request, jsonObj);
QEventLoop eloop;
QObject::connect(reply, &QNetworkReply::finished, &eloop, &QEventLoop::quit);
QObject::connect(reply, &QNetworkReply::errorOccurred, &eloop, &QEventLoop::quit);
eloop.exec();
ReplyData data;
if (reply->error() != QNetworkReply::NoError)
{
data.code = -2;
data.message = reply->errorString();
reply->deleteLater();
return data;
}
auto jsonStr = reply->readAll();
reply->deleteLater();
if (!jsonStr.isEmpty())
{
data.fromJson(jsonStr);
}
return data;
}
ReplyData Delete(const QString& url)
{
QNetworkAccessManager manager;
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json;charset=utf-8;");
QNetworkReply* reply = manager.deleteResource(request);
QEventLoop eloop;
QObject::connect(reply, &QNetworkReply::finished, &eloop, &QEventLoop::quit);
QObject::connect(reply, &QNetworkReply::errorOccurred, &eloop, &QEventLoop::quit);
eloop.exec();
ReplyData data;
if (reply->error() != QNetworkReply::NoError)
{
data.code = -2;
data.message = reply->errorString();
reply->deleteLater();
return data;
}
auto jsonStr = reply->readAll();
reply->deleteLater();
if (!jsonStr.isEmpty())
{
data.fromJson(jsonStr);
}
return data;
}
ReplyData Delete(const QUrl& url)
{
QNetworkAccessManager manager;
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json;charset=utf-8;");
QNetworkReply* reply = manager.deleteResource(request);
QEventLoop eloop;
QObject::connect(reply, &QNetworkReply::finished, &eloop, &QEventLoop::quit);
QObject::connect(reply, &QNetworkReply::errorOccurred, &eloop, &QEventLoop::quit);
eloop.exec();
ReplyData data;
if (reply->error() != QNetworkReply::NoError)
{
data.code = -2;
data.message = reply->errorString();
reply->deleteLater();
return data;
}
auto jsonStr = reply->readAll();
reply->deleteLater();
if (!jsonStr.isEmpty())
{
data.fromJson(jsonStr);
}
return data;
}
QUrl CreateQueryString(const QString& baseUrl, const QMap<QString, QString>& queryParams)
{
QUrl url(baseUrl);
QUrlQuery query;
//for (auto it = queryParams.constBegin(); it != queryParams.constEnd(); ++it) query.addQueryItem(it.key(), it.value());
for (const auto& key: queryParams.keys()) query.addQueryItem(key, queryParams.value(key));
url.setQuery(query);
return url;
}
};
Q_GLOBAL_STATIC(HttpClient, httpClient)
3. 定义数据模型类
我们使用QSerializer库来定义数据模型类,这些类将帮助我们解析和序列化JSON数据。以下是示例类:ReplyData
作为通用返回和模型类ShiftAnalyze
、CNCPosition
、PullMulti
。
#ifndef REPLY_DATA_H
#define REPLY_DATA_H
#include "qserializer.h"
class ReplyData : public QSerializer
{
Q_GADGET
QS_SERIALIZABLE
public:
ReplyData() = default;
QS_FIELD(int, code)
QS_FIELD(QString, message)
QS_FIELD(QJsonValue, data)
};
#endif
#ifndef SHIFT_ANALYZE_H
#define SHIFT_ANALYZE_H
#include "qserializer.h"
class ShiftAnalyze : public QSerializer
{
Q_GADGET
QS_SERIALIZABLE
public:
ShiftAnalyze() = default;
QS_FIELD(QString, shiftType)
QS_FIELD(float, totalPrintTime)
QS_FIELD(float, totalPrintWeight)
QS_FIELD(float, totalTemperatureTime)
QS_FIELD(float, totalIdleTime)
QS_FIELD(float, totalBackhaulTime)
QS_FIELD(float, totalArcSeekingTime)
};
#endif
#ifndef CNC_POSITION_H
#define CNC_POSITION_H
#include "qserializer.h"
class CNCPosition : public QSerializer
{
Q_GADGET
QS_SERIALIZABLE
public:
CNCPosition() = default;
QS_COLLECTION(QVector, QString, axis)
QS_COLLECTION(QVector, QString, units)
QS_COLLECTION(QVector, float, absoluteCoords)
QS_COLLECTION(QVector, float, relativeCoords)
QS_COLLECTION(QVector, float, machineCoords)
QS_COLLECTION(QVector, float, distances)
};
#endif
#pragma once
#include "qserializer.h"
class PullMulti : public QSerializer
{
Q_GADGET
QS_SERIALIZABLE
public:
QS_FIELD(QStringList, fCodes)
};
4. 处理HTTP响应
在主函数中,我们创建HttpClient
对象并发送GET请求。然后,我们使用QSerializer将返回的JSON数据解析为ShiftAnalyze
对象。
int main(int argc, char* argv[])
{
QCoreApplication a(argc, argv);
Person toWrite;
toWrite.age = 25;
toWrite.weight = 74.6;
toWrite.name = "linxmouse";
toWrite.fixedAddr = Address("jiangxia", "wuhan");
toWrite.languages = QStringList() << "c" << "c++" << "c#";
toWrite.scores = QVariantList() << 8 << 8 << 9;
toWrite.addresses = QVector<Address>() << Address("js", "jm") << Address("py", "gz");
qDebug() << toWrite.toRawJson().constData();
QFile write2Json("person.json");
if (write2Json.exists()) write2Json.remove();
if (write2Json.open(QIODevice::WriteOnly))
{
write2Json.write(toWrite.toRawJson());
write2Json.close();
}
QFile read2Object("person.json");
if (read2Object.exists())
{
if (read2Object.open(QIODevice::ReadOnly))
{
Person fromRead;
fromRead.fromJson(read2Object.readAll());
read2Object.close();
}
}
ReplyData data = httpClient->Get("http://localhost:9001/dps/service/GetPreviousShiftAnalyze");
if (data.code == 0)
{
ShiftAnalyze shiftAnalyze;
shiftAnalyze.fromJson(data.data);
}
QMap<QString, QString> parmas;
parmas["fcode"] = "cnc_position";
QUrl cnc_position = httpClient->CreateQueryString("http://localhost:9001/das/services/Pull", parmas);
ReplyData data1 = httpClient->Get(cnc_position);
if (data1.code == 0)
{
CNCPosition cncPosition;
cncPosition.fromJson(data1.data);
}
//PullMulti pullMulti;
//pullMulti.fCodes << "arc_voltage" << "rolling_force";
QJsonObject jsonObj;
jsonObj.insert("fCodes", QJsonArray() << "arc_voltage" << "rolling_force");
//ReplyData data2 = httpClient->Post("http://localhost:9001/das/services/PullMulti", pullMulti.toRawJson());
ReplyData data2 = httpClient->Post("http://localhost:9001/das/services/PullMulti", QJsonDocument(jsonObj).toJson());
if (data2.code == 0)
{
auto list = data2.data.toVariant().toStringList();
}
return a.exec();
}
通过本文,我们了解了如何在Qt5中使用QNetworkAccessManager
和QSerializer库来处理HTTP REST客户端请求,并解析JSON数据。通过定义数据模型类,我们可以方便地序列化和反序列化JSON数据,从而简化了与服务器的通信。