在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作为通用返回和模型类ShiftAnalyzeCNCPositionPullMulti

#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数据,从而简化了与服务器的通信。

posted @ 2024-06-27 18:26  非法关键字  阅读(241)  评论(0编辑  收藏  举报