【C++ QT项目实战-02】---- C++ QT系统实现基于QT调用RESTful接口访问JSON文件中数据

news2024/11/26 0:57:11

🎩 欢迎来到技术探索的奇幻世界👨‍💻

📜 个人主页@一伦明悦-CSDN博客

✍🏻 作者简介C++软件开发、Python机器学习爱好者

🗣️ 互动与支持💬评论      👍🏻点赞      📂收藏     👀关注+

如果文章有所帮助,欢迎留下您宝贵的评论!

欢迎点赞加收藏支持我,点击关注,一起进步!


目录

前言

正文

01-RESTful架构简介

02-QT中实现调用RESTful接口的类的介绍

(1)QT简介         

(2)QT中类的简介

(3)QT调用RESTful 接口步骤

03-系统实现调用RESTful接口代码介绍

(1)dialog_con.h文件解释  

(2)dialog_con.cpp文件解释

 04-C++ QT项目系统功能演示

总结


前言

         本篇在做项目的基础上进行了项目中难点的一些总结,我们都知道,在如今大数据时代下,数据对项目系统开发起到决定性的作用,可以帮助企业实现实时决策、提升用户体验、实现业务智能、提高系统性能、提供定制化服务和增强业务竞争力等方面的优势,有利于项目系统的发展和成功。因此,在项目系统开发过程中,需要充分重视数据的快速读取和处理能力,以满足日益增长的数据需求和用户期望。

        当然数据可以有多种的文件存储方式,比如JSON文件,CSV 文件,XML 是一种标记语言,用于存储和传输数据,Excel文件等等,对于各行各业来说,都会采用最适合自己的存储方式,因此,项目开发中的系统也就需要满足企业需要,对企业选定的存储文件进行访问,读取所需数据。

        本文是在项目中开发过程需要访问JSON格式的数据文件,项目系统基于C++ QT混合编程语言完成,因此,这里介绍一下完成这项功能时的一些难点,附上代码和运行过程解释。

正文

01-RESTful架构简介

         REST(英文:Representational State Transfer,简称REST,直译过来表现层状态转换)是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

        它首次出现在 2000 年 Roy Thomas Fielding 的博士论文中,这篇论文定义并详细介绍了表述性状态转移(Representational State Transfer,REST)的架构风格,并且描述了 如何使用 REST 来指导现代 Web 架构的设计和开发。用他自己的原话说:

        我写这篇文章的目的是:在符合架构原理前提下,理解和评估基于网络的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构

        REST是一种基于网络标准和 HTTP 协议的架构风格,用于设计分布式系统。它是一种轻量级、灵活的通信方式,强调资源的概念和统一的接口设计,符合 RESTful 架构的应用程序易于扩展、简单快捷。

        以下是 RESTful 架构的几个核心概念:

        资源(Resources):在 RESTful 架构中,每个可访问的信息单元都被视为一个资源。资源可以是任何可命名的实体,如文档、图像、服务等。每个资源都有唯一的标识符(URI)用于定位和访问。

        统一接口(Uniform Interface):RESTful 架构要求使用统一的接口对资源进行操作,包括对资源的创建、读取、更新和删除(CRUD)。常用的 HTTP 方法(GET、POST、PUT、DELETE)与资源的操作相对应。

        状态的表述性(Stateless):RESTful 服务端不会保存客户端状态,每个请求都包含了足够的信息进行处理。服务端无需记录客户端的状态,这样可以更好地实现系统的可伸缩性和容错性。

        自描述消息(Self-descriptive Messages):RESTful 架构使用标准的媒体类型(如 JSON、XML)来表示资源的信息,使客户端和服务器能够理解和处理资源的表述形式。

        超媒体驱动(Hypermedia Driven):RESTful 架构鼓励使用超媒体链接(如超文本链接)来为客户端提供资源的相关信息和操作链接,实现动态发现和关联性。

        下面对统一接口(Uniform Interface)概念详细解释一下:

        当讨论 RESTful 架构中的统一接口时,可以通过一个架构图形象地解释。以下是一个简单的 RESTful 架构图说明,展示了资源的 URI 和常用的 HTTP 方法,以及与 CRUD 操作相对应的请求和响应示例:

        说明

        客户端(Client):表示发起请求的用户或系统。

        资源服务器(Resource Server):表示存放资源的服务器端。

        URI(Uniform Resource Identifier):表示资源的唯一标识符。        

        HTTP 方法

                GET:用于获取资源的信息,对应查询操作。

                POST:用于创建新资源,对应创建操作。

                PUT:用于更新已有资源,对应更新操作。

                DELETE:用于删除资源,对应删除操作。

        请求和响应示例

                GET 请求 /api/books 返回所有书籍信息。

                POST 请求 /api/books 添加新书籍。

                PUT 请求 /api/books/123 更新特定书籍。

                DELETE 请求 /api/books/123 删除特定书籍。

                HTTP 状态码(例如 200、201、204)和响应数据格式(如 JSON)。

        这里清晰地展示了 RESTful 架构中的统一接口设计原则,通过使用统一的 HTTP 方法和资源的 URI 对资源进行操作。客户端通过向服务器发送不同的 HTTP 请求来实现对资源的创建、读取、更新和删除,从而实现了系统的简洁性、可扩展性和易用性。

        通过遵循 RESTful 架构的统一接口设计原则,开发人员可以更容易地构建符合标准的 API,使系统的接口更易于理解和维护,同时提供更好的互操作性和用户体验。

        下面是一个简单的示例代码,用 Python 的 Flask 框架实现一个简单的 RESTful API:在这个示例中,/books 是资源的 URI,GET 方法用于获取书籍列表,POST 方法用于添加新书籍。客户端可以发送 HTTP 请求来访问资源并执行相应的操作。

from flask import Flask, jsonify, request

app = Flask(__name__)
books = []

# 获取所有书籍
@app.route('/books', methods=['GET'])
def get_books():
    return jsonify(books)

# 添加新书籍
@app.route('/books', methods=['POST'])
def add_book():
    data = request.get_json()
    books.append(data)
    return jsonify({'message': 'Book added successfully'})

if __name__ == '__main__':
    app.run()

02-QT中实现调用RESTful接口的类的介绍

(1)QT简介         

        Qt 是一个跨平台的 C++ 应用程序开发框架,最初由挪威的 Trolltech 公司开发,现由 Digia 公司维护。Qt 提供了一套完整的工具和库,使开发人员能够轻松地构建图形用户界面(GUI)、网络应用程序、嵌入式应用程序等各种类型的应用程序。

        以下是 Qt 框架的一些主要特点和组件:

        跨平台支持:Qt 提供了一致的 API,能够在多个操作系统上运行,包括 Windows、macOS、Linux、Android 等。开发人员可以使用相同的代码库开发跨平台的应用程序。

        GUI 开发:Qt 提供了丰富的 GUI 类库,包括 QWidget、QML、Qt Quick 等,以及用户友好的设计器工具,使开发人员可以轻松地创建现代化的用户界面。

        网络和通信:Qt 包含了网络模块,如 QNetworkAccessManager,用于处理网络请求和通信。同时也支持 WebSockets、TCP/IP、UDP 等网络通信协议。

        数据库支持:Qt 提供了跨平台的数据库访问类,如 QSqlDatabase,可以和主流的数据库系统(如 MySQL、SQLite、PostgreSQL)进行集成。

        图形和多媒体:Qt 支持图形渲染、图像处理和多媒体功能,开发人员可以轻松地处理图形、音频和视频数据。

        跨平台部署工具:Qt 提供了一套工具链,包括 Qt Creator 集成开发环境、Qt Installer Framework 等,能够帮助开发人员打包和部署应用程序到不同的平台。

        开源社区支持:Qt 拥有活跃的开源社区,不仅提供了大量的文档、示例和第三方库,还有专门的邮件列表和论坛,开发人员可以在社区中获取支持和交流经验。

        总的来说,Qt 是一个功能强大、跨平台且易于学习的应用程序开发框架,适用于各种类型的应用程序开发,无论是桌面应用、移动应用、嵌入式应用还是其他类型的应用。开发人员可以通过 Qt 快速构建高质量的应用程序,并轻松地将其部署到不同的平台上。

(2)QT中类的简介

        当涉及到使用 Qt 进行网络访问和 JSON 数据处理时,QNetworkAccessManager 和 QJsonDocument 是两个重要的类。

        QNetworkAccessManager

        介绍:QNetworkAccessManager 是 Qt 提供的网络请求和响应管理类,用于处理网络通信。通过 QNetworkAccessManager,可以发送 HTTP 请求、处理响应,并管理网络请求的会话。

        功能:发送 GET、POST、PUT、DELETE 等 HTTP 请求。支持同步和异步网络操作。提供自定义请求头、身份验证和代理设置。支持重定向和 Cookie 管理。

        示例代码:以下是一个简单的示例代码,使用 QNetworkAccessManager 发送 HTTP GET 请求并处理响应:

QNetworkAccessManager *manager = new QNetworkAccessManager(this);
QNetworkReply *reply = manager->get(QNetworkRequest(QUrl("https://jsonplaceholder.typicode.com/posts/1")));
connect(reply, &QNetworkReply::finished, [=](){
    if(reply->error() == QNetworkReply::NoError){
        QByteArray responseData = reply->readAll();
        qDebug() << "Response data: " << responseData;
    }
    reply->deleteLater();
});

        QJsonDocument

        介绍:QJsonDocument 是 Qt 提供的 JSON 数据处理类,用于解析和生成 JSON 数据。通过 QJsonDocument,可以方便地读取和修改 JSON 数据。

        功能:将 JSON 数据转换为 QVariant 对象以便读取。将 QVariant 对象转换为 JSON 数据以便输出。支持从 JSON 字符串、二进制、以及 QJsonObject、QJsonArray 等类型创建 QJsonDocument 对象。

        示例代码:以下是一个简单的示例代码,使用 QJsonDocument 解析 JSON 数据:

QByteArray json = "{\"key\":\"value\"}";
QJsonDocument jsonDoc = QJsonDocument::fromJson(json);
if(!jsonDoc.isNull() && jsonDoc.isObject()){
    QJsonObject jsonObj = jsonDoc.object();
    QString value = jsonObj["key"].toString();
    qDebug() << "Value: " << value;
}

        通过使用 QNetworkAccessManager 和 QJsonDocument,开发人员可以方便地实现网络请求和 JSON 数据处理的功能,从而与远程服务器进行通信、获取数据和处理 JSON 数据。这两个类为 Qt 应用程序的网络通信和数据处理提供了强大的支持。       

(3)QT调用RESTful 接口步骤

        在 C++ 中使用 Qt 框架来调用 RESTful 接口并访问 JSON 文件中的数据通常需要以下步骤:

        创建Qt项目:首先需要创建一个 Qt 项目,确保项目中包含了网络模块,可以通过 Qt Creator 创建一个新的 Qt 控制台应用程序。

        发送HTTP请求:使用 Qt 的 QNetworkAccessManager 类来发送 HTTP 请求。通过创建一个 QNetworkRequest 对象,设置请求的 URL、请求头等信息,然后使用 QNetworkAccessManager 发送该请求。

        处理响应:在发送请求后,Qt 的 QNetworkAccessManager 会发送信号来处理响应。在收到响应后,可以读取 JSON 数据并进行处理。

        解析JSON:Qt 提供了 QJsonDocument 类来解析和操作 JSON 数据。可以使用 QJsonDocument::fromJson() 方法将接收到的 JSON 字符串转换为 QJsonDocument 对象,然后通过该对象获取 JSON 数据中的内容。

        处理数据:一旦获得了 JSON 数据,你可以根据需要提取其中的数据并进行进一步处理,例如显示到界面上或者进行其他业务逻辑操作。

        错误处理:在实际应用中,需要考虑网络请求失败、JSON 解析错误等异常情况的处理,确保程序的稳定性和可靠性。

         这是一个简单的示例代码,演示了如何在 C++ 中使用 Qt 访问 RESTful 接口并读取 JSON 数据:

#include <QCoreApplication>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QNetworkAccessManager manager;
    QNetworkRequest request(QUrl("https://api.example.com/data"));
    QNetworkReply *reply = manager.get(request);

    QObject::connect(reply, &QNetworkReply::finished, [&](){
        if(reply->error() == QNetworkReply::NoError){
            QByteArray response = reply->readAll();
            QJsonDocument jsonDoc = QJsonDocument::fromJson(response);
            QJsonObject jsonObject = jsonDoc.object();
            
            // 处理 JSON 数据
            // 例如:打印所有键值对
            for(auto it = jsonObject.begin(); it != jsonObject.end(); ++it){
                qDebug() << it.key() << ":" << it.value();
            }
        } else {
            qDebug() << "Network request failed: " << reply->errorString();
        }

        // 释放资源
        reply->deleteLater();
    });

    return a.exec();
}

03-系统实现调用RESTful接口代码介绍

       下面给出项目实现基于QT调用RESTful接口的代码,演示过程下一小节进行,这里仅对代码进行详细解释,代码分为两部分,首先是dialog_con.h通信的.h文件,后面是dialog_con.cpp通信的.cpp文件,代码解释如下:

        (1)dialog_con.h文件解释  

        这段 C++ Qt 代码主要定义了一个名为 Dialog_con 的类,这个类继承自 QDialog,并包含了一些成员变量、成员函数以及信号与槽函数。代码解释如下:

  1. 头文件包含部分

    • 通过 #pragma once 和 #ifndef...#endif 语句来确保头文件只被包含一次,避免重复定义。
    • 包含了一系列需要使用的头文件,例如 Qt 相关的头文件、第三方库的头文件等。
  2. 命名空间

    • 使用 namespace Ui 包含了一个名为 Dialog_con 的类的声明。
  3. Dialog_con 类

    • 公有成员函数:定义了类的公有成员函数,例如构造函数、析构函数以及处理网络请求的函数。
    • 成员变量:定义了一系列成员变量,包括各种配置信息、JSON 数据解析相关的变量,以及结构体 hdgl_predict_data 和其他结构体变量。
    • 私有成员函数:定义了一些私有函数用于处理内部逻辑,如解析 JSON 数据、将字节转换为浮点数等。
    • 槽函数:定义了一系列槽函数,对应不同的按钮点击事件,如发送 GET 请求、发送 POST 请求、配置参数等。
    • 信号:定义了一个信号 showmain(),可以在需要时发射信号。
  4. 结构体

    • 定义了一个名为 hdgl_predict_data 的结构体,包含了预测数据的各个字段。
    • 其他结构体变量用于存储不同类型的测量数据。
  5. 函数实现

    • 实现了一些函数,包括将字节数组转换为浮点数、解析 JSON 数据等功能。
    • 实现了各个按钮点击事件的处理函数,如返回主菜单、退出登录等。
    • 实现了读取配置信息的函数。

        总体而言,这段代码主要实现了一个用于与 PLC 进行通信和处理数据的对话框类。其中包括了网络请求、数据解析、按钮点击事件处理等功能。每个成员变量和函数都承担着不同的功能,以实现对话框类的各种操作和逻辑。

#pragma once
#ifndef DIALOG_CON_H
#define DIALOG_CON_H
#include "ui_dialog_login.h"
//#include "ui_mainwindow.h"
//#include "ui_MainWindow1.h"
#include "dialog_con.h"
#include "ui_Dialog_con.h"

//#include "MainWindow1.h"

#include <QTimer>
#include <QTime>
#include "snap7.h"

#include <QDialog>
#include <QAbstractButton>
#include <QPushButton>
#include "mainwindow.h"
#include"ui_mainwindow.h"

// #include <QtWidgets/QMainWindow>
#include <QtCore/QJsonObject>
#include <QtCore/QJsonDocument>


enum MyMethod
{
	GET,
	POST
};


namespace Ui {
	class Dialog_con;

}

class Dialog_con : public QDialog
{
	Q_OBJECT


public:
	explicit Dialog_con(QWidget *parent = 0);
	~Dialog_con();

	void SendAndGetText(QString strUrl, MyMethod thod, QString strInput, QString &strMessage, QString &strResult);

public:
	int query_step = 1000;
	int heartbeat;


	QString clientID, clientSecret, serverIP, serviceID_get, serviceID_post, user_ID, companyCode;

	QString name, unit;

	QString mssql_serverName, mssql_dbName, mssql_username, mssql_pwd, mssql_datasource;
	QString oraclexe_serverName, oraclexe_port, oraclexe_dbName, oraclexe_username, oraclexe_pwd;
	QJsonDocument json_doc_get;
	QJsonObject doc_get_Obj;


private:
	//MainWindow q;
	Ui::Dialog_con *ui;
	TS7Client *ptrPLC;
	QTimer *timer_PLC_hf = new QTimer(this);
	float ByteToFloat(unsigned char* byteArray);
	int Dialog_con::ByteToInt(unsigned char* byteArray);

	void json_doc_get_parse();

public slots:

    void OnGETSlot();
	void OnPOSTSlot();
	void OnconfigSlot();
	bool configuration_read();


private slots:
	//void on_login_ok_Btn_clicked();
	//void on_data_import_Btn_clicked(QAbstractButton *button);
	//void on_login_ok_Btn_clicked(QAbstractButton * button);
	//private slots:
//	void on_Btn_PLC_rw_check_clicked();
	void on_Btn_Ret_clicked();                   //返回主菜单
	void on_Btn_exit_clicked();                  //退出登入
//	void read_write_PLC();
signals: 
	/**
	* 信号必须要signals关键字来声明
	* 信号没有返回值, 但可以有参数
	* 信号就是函数的声明, 无需定义
	* 使用: emit mySignal();
	* 信号可以被重载
	*/
	//void showmain();

private:

	struct hdgl_predict_data   
	{
		QString hdgl_predict_id;
		QString ENTID; 
		QString ATIME;  
		QString ST_code;
		QString ST_grade;
		QString ST_source;
		QString cal_datetime;
		QString finish_datetime;

		 
		float CH_C;


	};   // 忘加分号




public:

	hdgl_predict_data strt_hdgl_predict;

	WFC_TEMP_MEASURE wfc_temp_measure;  // 
	WFC_FLATNESS_MEASURE wfc_flatness_measure;  //
	WFC_VALVE_FLOW_MEASURE wfc_valve_flow_measure; //
	WFC_COIL_PROCESS_INFO wfc_coil_process_info;  //
	WFC_VALVE_FLOW_PRESET wfc_valve_flow_preset;  //这里和子线程不一样

};


#endif // DIALOG_CON_H

(2)dialog_con.cpp文件解释

        这段代码主要是关于网络请求的处理,包括发送 POST 和 GET 请求,并处理返回的数据。下面是对每一行代码的解释:

   void Dialog_con::SendAndGetText(QString strUrl, MyMethod thod, QString strInput, QString &strMessage, QString &strResult): 定义了一个函数 SendAndGetText,接受URL、请求方法、输入参数、以及两个输出参数用于保存消息和结果。

   QNetworkRequest oNetRequest, post_NetRequest;: 声明了两个网络请求对象 oNetRequest 和 post_NetRequest

   QJsonObject json;: 声明一个 JSON 对象用于构建 JSON 数据。

   QJsonDocument document;: 声明一个 JSON 文档对象。

   QString cgl_result;: 声明一个字符串变量用于保存结果。

   QUrlQuery url_Query;: 声明一个 URL 查询对象。

   QString url_Request;: 声明一个字符串变量用于保存请求的 URL。

   oNetRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);: 设置网络请求的属性,允许自动跟随重定向。

   post_NetRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);: 设置另一个网络请求的属性,同样允许自动跟随重定向。

   QUrl url(strUrl);: 根据传入的 URL 字符串创建一个 URL 对象。

   bytes.append(QString("name=%1").arg(name));: 将数据添加到字节数组中。

   url_Query.addQueryItem("name", name);: 将查询参数添加到 URL 查询对象中。

   url.setQuery(url_Query);: 将查询参数设置到 URL 对象中。

   qDebug() << url;: 输出 URL 信息。

   oNetRequest.setUrl(url);: 设置一个网络请求的 URL。

   post_NetRequest.setUrl(url);: 设置另一个网络请求的 URL。

        接下来是一系列关于 JSON 数据处理的代码,包括构建 JSON 数据和设置请求的头部信息等。

   QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);: 创建一个用于发送表单数据的 HTTP 多部分对象。

        接下来是构建 POST 请求的具体数据部分,包括参数和内容的设置。

   QNetworkAccessManager oNetAccessManager;: 创建一个网络访问管理器对象。

   QNetworkReply* oNetReply = NULL;: 声明一个网络回复对象。

        根据请求方法(GET 或 POST)发送网络请求,并等待请求完成。

        处理请求完成后的相关逻辑,包括读取返回数据、处理错误信息等。

   void Dialog_con::OnPOSTSlot(): 定义了一个槽函数 OnPOSTSlot,用于处理 POST 请求。

   void Dialog_con::OnGETSlot(): 定义了一个槽函数 OnGETSlot,用于处理 GET 请求。

   file.write(json_doc_get.toJson(QJsonDocument::Indented));: 将获取到的 JSON 数据写入文件。

        以上是对代码中每一行的简要解释,涵盖了网络请求的发送和处理、JSON 数据的构建和解析等内容。

        接下来的这部分代码主要包括两个函数:json_doc_get_parse 和 extractJsonValue

        1. json_doc_get_parse 函数:

        这个函数用于解析 JSON 文档 json_doc_get 中的数据。

        首先判断 json_doc_get 是否为空,如果为空则记录错误信息;否则记录解析开始信息。

        接着判断 doc_get_Obj 中是否包含键名为 “Coil_first” 的对象。

        如果有,就获取该对象,并从中提取出特定的键值信息(如 aentid、atime、acode、agrade、asource、C 等)。

        使用 extractJsonValue 函数来提取 task_zone0_Obj 中的 “C_CH” 键对应的值,并将结果存储在变量 C 中。

        将提取的信息赋值给 strt_hdgl_predict 结构体中的对应成员变量,并更新 UI 上相关的文本框内容。

        2. extractJsonValue 模板函数:

        这是一个通用的模板函数,用于从 QJsonObject 对象中提取特定类型的值。

        参数包括一个 QJsonObject 对象和一个键名 key

        通过 obj[key] 获取对应键的值,然后通过 toVariant() 转换为 QVariant 类型,最后通过 value<T>() 转换为指定的类型 T 并返回。

        综上所述,json_doc_get_parse 函数用于解析 JSON 数据并更新 UI,而 extractJsonValue 函数则作为一个通用的值提取函数被调用。请注意,以上是根据提供的代码片段推断的解释,具体情况可能还需要参考其他相关代码来确定。

//#include "ui_MainWindow1.h"
#include "ui_dialog_pred_init.h"
#include "ui_dialog_data_log.h"
#include "ui_dialog_login.h"
//#include "ui_mainwindow.h"
#include "ui_dialog_pred_init.h"
#include "ui_dialog_data_log.h"
#include "ui_dialog_login.h"

#include "dialog_con.h"
#include "windows.h"
#include "qdebug.h"
#include <qstring.h>
#include "mainwindow.h"
#include"ui_mainwindow.h"
#pragma comment(lib,".\\lib\\fmtd.lib")

#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <QUrlQuery>
#include <QHttpMultiPart>
#include <QtCore/QJsonObject>
#include <QtCore/QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonParseError>
#include <QJsonValue>
#include <QSysInfo>
#include <QSslSocket>

#include "spdlog/fmt/ostr.h"
#include "spdlog/spdlog.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include <memory>
#include <string>

#include <QTimer>
#include "snap7.h"


#include <QSqlError>
#include <QSqlDatabase>
#include <QSqlQuery>


#include "snap7.h"
#pragma comment(lib,"snap7.lib")
using namespace std::literals;
using namespace std;
namespace spd = spdlog;

auto console_con = spd::stdout_color_mt("Iplat4j大数据平台通讯测试");

auto rotating_logger_con = spdlog::rotating_logger_mt("baori_CA08_Iplat4j_chk_rotating", "logs/baori_CA08_rotating.logger", 1048576 * 5, 12);


Dialog_con::Dialog_con(QWidget *parent) :
	QDialog(parent),
	ui(new Ui::Dialog_con)
{
	ui->setupUi(this);
	setWindowTitle(QString::fromLocal8Bit("基础通信"));
	//configuration_read();
	connect(ui->Config_Btn, SIGNAL(clicked()), this, SLOT(OnconfigSlot()));
	connect(ui->GET_Btn, SIGNAL(clicked()), this, SLOT(OnGETSlot()));

}

Dialog_con::~Dialog_con()
{
	delete ui;
}


void Dialog_con::SendAndGetText(QString strUrl, MyMethod thod, QString strInput, QString &strMessage, QString &strResult)
{

	QNetworkRequest oNetRequest, post_NetRequest;
	QJsonObject json;
	QJsonDocument document;
	QString cgl_result;
	QUrlQuery url_Query;
	QString url_Request;

	oNetRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); //让Qt自动为你跳转
	post_NetRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); //让Qt自动为你跳转

	QUrl url(strUrl);



	QByteArray bytes;
	bytes.append(QString("name=%1").arg(name));  // Qt 作为变量输入
	bytes.append(QString("unit=%1").arg(unit));  // Qt 作为变量输入
	url_Query.addQueryItem("name", name);
	url_Query.addQueryItem("unit", unit);

	url.setQuery(url_Query);

	//QUrl url(strUrl);
	qDebug() << url;

	oNetRequest.setUrl(url);
	post_NetRequest.setUrl(url);


	QByteArray dataArray;


	float THF = 100.0;
	cgl_result = "THF:" + QString::number(THF, 'f', 2);

	// Json数据提交
	json.insert("age", "25");
	json.insert("user", "APIInfo");


	document.setObject(json);

	dataArray = document.toJson(QJsonDocument::Compact);


	QHttpPart part_token;
	QHttpPart part_name, part_unit;
	QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);

	part_name.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
	part_name.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"name\""));
	part_name.setBody(name.toUtf8());

	part_name.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
	part_name.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"unit\""));
	part_name.setBody(unit.toUtf8());

	multiPart->append(part_name);
	multiPart->append(part_unit);

	oNetRequest.setRawHeader("Content-Type", "application/json");
	post_NetRequest.setRawHeader("Content-Type", "application/json");

	QByteArray params;
	//QByteArray bodyData;

	QString tokenInfo = strInput;

	//tokenInfo = tokenInfo + ": ";
	QByteArray tokenData = tokenInfo.toLocal8Bit().toBase64();
	QString headerData = "Token " + tokenData;

	params.append("access_token=" + tokenInfo);
	params.append("access_token=");

	QString ss1 = strInput.toLocal8Bit();

	QNetworkAccessManager oNetAccessManager;
	QNetworkReply* oNetReply = NULL;
	QByteArray inputTmp;
	if (thod == POST)
	{
		
		oNetReply = oNetAccessManager.post(post_NetRequest, dataArray);
	}
	else if (thod == GET)
	{
		oNetReply = oNetAccessManager.get(oNetRequest);
	}

	QEventLoop loop;
	connect(oNetReply, SIGNAL(finished()), &loop, SLOT(quit()));
	loop.exec();

	//记录httpCode
	int httpsCode = oNetReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();

	QNetworkReply::NetworkError e = oNetReply->error();
	strResult = oNetReply->readAll();
	if (e)
	{
		strMessage = oNetReply->errorString();
		console_con->error("Iplat4j大数据平台连接失败[Dialog_con]!");
		
	}
	else 
	{
		console_con->info("http连接正常");

		console_con->info("Iplat4j大数据平台连接成功[Dialog_con]!");
		
	



	}
}
void Dialog_con::OnPOSTSlot()
{

	QString strMessage;
	QString strResult;
	QString strUrl;
	QString strInput;

	strUrl = serverIP + serviceID_post;
	strInput = clientSecret;

	SendAndGetText(strUrl, POST, strInput, strMessage, strResult);
	ui->Url_QLE->setText(strUrl);
	ui->ErrorMessage_QTE->setText(strMessage);
	ui->Result_QTE->setText(strResult);
}

void Dialog_con::OnGETSlot()
{
	QString strMessage;
	QString strResult;
	QString strUrl;
	QString strInput;
	QFile file(QApplication::applicationDirPath() + "/1.json");
	if (!file.open(QIODevice::WriteOnly)) {
		qDebug() << "File open failed!";
	}
	else {
		qDebug() << "File open successfully!";
	}


	strUrl = serverIP + serviceID_get;
	strInput = clientSecret;
	SendAndGetText(strUrl, GET, strInput, strMessage, strResult);

	QJsonParseError jsonError;
	QByteArray byteResult = strResult.toUtf8();//QString转QByteArray
											   //QJsonDocument json = QJsonDocument::fromJson(byteResult, &jsonError);
	json_doc_get = QJsonDocument::fromJson(byteResult, &jsonError);

	if (json_doc_get.isNull())
	{
		console_con->critical("json文件为空文档");
		
		rotating_logger_con->critical("json格式错误[json_doc_get_slot]");
		
	}
	else if (jsonError.error != QJsonParseError::NoError)
	{
		console_con->critical("json格式错误[json_doc_get_slot]" + jsonError.errorString().toStdString());
		//qDebug() << jsonError.errorString();
		rotating_logger_con->critical("json格式错误[json_doc_get_slot]");
	}
	else {
		if (json_doc_get.isObject()) {
			doc_get_Obj = json_doc_get.object();
		}
	}
	json_doc_get_parse();

	file.write(json_doc_get.toJson(QJsonDocument::Indented)); //Indented:表示自动添加/n回车符
	file.close();
	ui->Url_QLE->setText(strUrl);
	ui->ErrorMessage_QTE->setText(strMessage);
	ui->Result_QTE->setText(strResult);

}


// 这里就是打开配置文件的
void Dialog_con::OnconfigSlot()
{
	configuration_read();
}
bool Dialog_con::configuration_read()
{
	string err;
	QFile config_ini("config.ini");
	//QFile config_ini("config_baori.ini");  打开baori配置文件,如果需要访问宝日大数据平台,就需要打开baori配置文件
	if (!config_ini.open(QIODevice::ReadOnly | QIODevice::Text))
	{
		console_con->critical("配置文件config.ini不能打开!");
		rotating_logger_con->critical("配置文件config.ini不能打开!");
		//		std::cout << "configuration.ini Open failed." << endl;
		return false;
	}
	console_con->info("配置文件config.ini已打开! ");
	rotating_logger_con->info("配置文件config.ini已打开! ");

	QTextStream config_txtInput(&config_ini);
	QString config_lineStr;

	config_lineStr = config_txtInput.readLine();

	config_lineStr = config_txtInput.readLine();
	clientID = config_lineStr.mid(9);
	config_lineStr = config_txtInput.readLine();
	clientSecret = config_lineStr.mid(13);
	config_lineStr = config_txtInput.readLine();
	serverIP = config_lineStr.mid(9);
	config_lineStr = config_txtInput.readLine();
	serviceID_get = config_lineStr.mid(14);
	config_lineStr = config_txtInput.readLine();
	serviceID_post = config_lineStr.mid(15);


	

	return true;
}

template<typename T>
T extractJsonValue(const QJsonObject& obj, const QString& key) {
	QVariant variant = obj[key].toVariant();
	return variant.value<T>();
}

void Dialog_con::json_doc_get_parse()
{

	//总的思路是:对象.value(),如果取到string、int、double类型 就直接.toString()等输出;
	//如果取到object或array类型 ,就通过toObject()或toArray() 转到对象或数组类型,接着取值。。循环
	if (json_doc_get.isNull())
	{
		console_con->critical("unable to parse! ");
		rotating_logger_con->critical("unable to parse! ");
	}
	else
	{
		console_con->info("parse start! ");
		rotating_logger_con->info("parse start! ");
	}
	
	if (doc_get_Obj.contains(QStringLiteral("Coil_first")))
	{
		
		QJsonObject task_zone0_Obj = doc_get_Obj["Coil_first"].toObject();
		QString aentid,atime, acode, agrade, asource;
		
		aentid = task_zone0_Obj["aentid"].toString();
		atime = task_zone0_Obj["atime"].toString();
		acode = task_zone0_Obj["acode"].toString();
		agrade = task_zone0_Obj["agrade"].toString();
		asource = task_zone0_Obj["asource"].toString();
		// 使用方式
		float C = extractJsonValue<float>(task_zone0_Obj, "C_CH");


		strt_hdgl_predict.ENTID = aentid;
		strt_hdgl_predict.ATIME = atime;
		strt_hdgl_predict.ST_code = acode;
		strt_hdgl_predict.ST_grade = agrade;
		strt_hdgl_predict.ST_source = asource;
		strt_hdgl_predict.CH_C = C;
	

		ui->ENTID_QLE->setText(strt_hdgl_predict.ENTID);
		ui->ATIME_QLE->setText(strt_hdgl_predict.ATIME);
		ui->ST_code_QLE->setText(strt_hdgl_predict.ST_code);
		ui->ST_grade_QLE->setText(strt_hdgl_predict.ST_grade);
		ui->ST_source_QLE->setText(strt_hdgl_predict.ST_source);

		ui->CH_C_QLE->setText(QString("%1").arg(QString::number(strt_hdgl_predict.CH_C, 'f', 4)));
		
	}
	//	}


}


void Dialog_con::on_Btn_Ret_clicked()
{
  this->hide();
  MainWindow *qMainWindow = new MainWindow();
  qMainWindow->show();
}

// 退出登入界面,这里对于按钮槽函数命名直接以on_按钮名_信号名命名,因此无需调用connect函数
// 当然槽函数需要在.h文件中进行定义
void Dialog_con::on_Btn_exit_clicked()
{
 this->hide();
 Dialog_login *login = new Dialog_login();         //登入界面显示
 login->show();
}
float Dialog_con::ByteToFloat(unsigned char* byteArray)
{
	return *((float*)byteArray);
}

int Dialog_con::ByteToInt(unsigned char* byteArray)
{
	return *((int*)byteArray);
}

04-C++ QT项目系统功能演示

        首先,需要配置一个JSON文件的环境,里面存储了一部分数据,用于模拟读取过程,这里是使用Java语言进行模拟的JSON环境,如下图所示,必须运行之后,C++系统才可以进行访问,并且需要访问同一网址才行。

        如下图所示,为系统登录界面,登录之后,才可以对各种功能进行操作。

        如下图所示,为通信界面,在这里可以模拟访问JSON文件数据,并且在对应控件上显示出来

         点击打开配置文件,然后再点击读取数据按钮,即可读取JSON文件中的所有数据,在结果显示中便可以查看。

总结

         使用 Qt 调用 RESTful 接口来访问 JSON 文件数据的方式具有以下优点:

        跨平台性:Qt 是跨平台的开发框架,可以在多种操作系统上运行,包括 Windows、macOS、Linux 等,因此可以保证应用在不同平台上的一致性。

        简洁易用:Qt 提供了丰富的网络模块和 JSON 处理功能,使得编写网络请求和数据解析的过程变得简单和直观。

        强大的网络支持:QNetworkAccessManager 提供了对网络请求的支持,可以方便地发送 HTTP 请求并处理响应,支持常见的 HTTP 请求方法,如 GET、POST 等。

        良好的异步处理:Qt 采用事件驱动的机制,在处理网络请求时能够实现异步操作,防止阻塞主线程,使得应用在进行网络通讯时仍然能够保持响应性。

        丰富的错误处理:通过监视请求的错误状态,可以对网络请求中可能出现的各种错误情况进行处理,保证应用的稳定性和可靠性。

        总的来说,使用 Qt 调用 RESTful 接口访问 JSON 文件数据的方式具有高效、稳定和可靠的特点,能够帮助开发者快速地实现网络数据的获取和处理,提高开发效率和用户体验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1711965.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

股票交易vip快速通道有什么门槛?vip交易通道的开通流程!

证券公司的VIP通道通常是为了满足高端客户或高频交易客户的需求而设立的&#xff0c;提供更快速、更便捷的交易服务。证券公司VIP通道适用于有追涨停板需求的投资者&#xff0c;以及一些喜爱高频交易的投资者&#xff0c;总的来说就是快速&#xff0c;在交易主机排队靠前。 VI…

视频集中存储LntonCVS视频监控汇聚平台智慧园区应用方案

智慧园区&#xff0c;作为现代化城市发展的重要组成部分&#xff0c;承载着产业升级的使命&#xff0c;是智慧城市建设的重要体现。在当前产业园区竞争日益激烈的情况下&#xff0c;越来越多的用户关注如何将项目打造成完善的智慧园区。 在智慧园区的建设过程中&#xff0c;各类…

离线deb安装下载及安装实例

1、使用apt download下载deb安装包(不包括依赖包) 1.1仅下载deb安装包 sudo apt download lrzsz 1.2安装载deb安装包 sudo dpkg -i lrzsz_0.12.21-10kylin0k2_arm64.deb 注&#xff1a;dpkg安装deb包&#xff0c;部分存在depends关系&#xff0c;需要使用apt-get -f instal…

【赠书第25期】C#项目开发实战(微视频版)

文章目录 前言 1 项目构思与需求分析 1.1 项目构思 1.2 需求分析 2 系统设计 2.1 系统架构设计 2.2 数据库设计 2.3 接口设计 3 编码实现 3.1 环境搭建 3.2 编码规范 3.3 编码实现 4 测试与部署 4.1 单元测试 4.2 系统测试 4.3 部署与上线 5 总结与展望 6 推…

信息安全法规和标准

《全国人民代表大会常务委员会关于维护互联网安全的决定》规定&#xff0c;威胁互联网运行安全的行为&#xff1a;&#xff08;1&#xff09;侵入国家事务、国防建设、尖端科学技术领域的计算机信息系统&#xff0c;&#xff08;2&#xff09;故意制作、传播计算机病毒等破坏性…

气膜建筑的运行保障:应对停电的解决方案—轻空间

气膜建筑作为一种现代化的建筑形式&#xff0c;以其独特的结构和多样的应用赢得了广泛关注。这种建筑依靠风机不断往内部吹气来维持其结构形态&#xff0c;那么如果遇到停电的情况&#xff0c;该如何确保其正常运行呢&#xff1f; 气膜建筑的供风系统 气膜建筑内部的气压维持依…

使用`War`包部署`Jenkins`(超级详细)

使用War包部署Jenkins(超级详细) 别着急&#xff0c;你看这年复一年&#xff0c;春光不必趁早&#xff0c;冬霜不会迟到。过去的都会过去&#xff0c;该来的都在路上&#xff0c;一切都是刚刚好。 网站说明 https://get.jenkins.io/war-stable/ war包下载地址 https://www.jenk…

Metasploit渗透测试工具使用

Metasploit Framework(MSF) 是一款开源安全漏洞检测工具&#xff0c;附带数千个已知的软件漏洞&#xff0c;并保持持 续更新。Metasploit可以用来信息收集、漏洞探测、漏洞利用等渗透测试的全流程&#xff0c;被安全社区冠以“可 以黑掉整个宇宙”之名。刚开始的Metasploit是采…

Steamdeck使用Windows系统游玩雪地奔驰时闪退问题解决方法

我非常喜欢雪地奔驰这款游戏&#xff0c;买sd的一部分也是为了它。可在我打开这个游戏时&#xff0c;游戏发生闪退问题。查阅了网络各个途径&#xff0c;基本没有解决方法。因此我自己分析终于解决该问题。以下是我解决问题的思路&#xff0c;仅供记录参考&#xff1a; 游戏在崩…

uniapp - 填充页面

在上一篇文章中&#xff0c;创建了一个空白的文章模块页面。在这一篇文章&#xff0c;让我们来向页面中填充内容。 目录 页面效果涉及uniapp组件1.view2.swiper3.scroll-view4.属性解读1) class"style1 style2 .."2) circular单属性无赋值3) :autoplay"autoplay…

大型跨境商城系统平台的技术架构分析

随着全球化的深入发展&#xff0c;大型跨境电商平台在如今的商业环境中扮演着越来越重要的角色。这些平台不仅仅是为了提供商品和服务&#xff0c;它们更是连接不同国家和地区消费者与供应商之间的桥梁。在这篇博客中&#xff0c;我们将深入探讨大型跨境商城系统平台的技术架构…

目标检测——家庭日常用品数据集

引言 亲爱的读者们&#xff0c;您是否在寻找某个特定的数据集&#xff0c;用于研究或项目实践&#xff1f;欢迎您在评论区留言&#xff0c;或者通过公众号私信告诉我&#xff0c;您想要的数据集的类型主题。小编会竭尽全力为您寻找&#xff0c;并在找到后第一时间与您分享。 …

7 Series FPGAs Integrated Block for PCI Express IP核设计中的物理层控制核状态接口

物理层控制和状态允许用户应用程序根据数据吞吐量和电源需求来更改链路的宽度和速度。 1 Design Considerations for a Directed Link Change 在Directed Link Change&#xff08;定向链接更改&#xff09;期间需要注意的事项有&#xff1a; 链接更改操作&#xff08;Link c…

加氢站压缩液驱比例泵放大器

加氢站压缩液驱液压系统的要求是实现换向和速度控制&#xff0c;对液压动力机构而言&#xff0c;按原理可区分为开式&#xff08;阀控&#xff09;- 节流控制系统和闭式&#xff08;泵控&#xff09;- 容积控制系统&#xff1a; 阀控系统 – 节流调速系统&#xff1a;由BEUEC比…

dp秒杀优惠券

1、全局id生成器 当用户抢购时&#xff0c;就会生成订单并保存到tb_voucher_order这张表中&#xff0c;而订单表如果使用数据库自增ID就存在一些问题&#xff1a; id的规律性太明显受单表数据量的限制 场景分析&#xff1a;如果我们的id具有太明显的规则&#xff0c;用户或者…

【机器学习】解锁AI密码:神经网络算法详解与前沿探索

&#x1f440;传送门&#x1f440; &#x1f50d;引言&#x1f340;神经网络的基本原理&#x1f680;神经网络的结构&#x1f4d5;神经网络的训练过程&#x1f686;神经网络的应用实例&#x1f496;未来发展趋势&#x1f496;结语 &#x1f50d;引言 随着人工智能技术的飞速发…

设计模式六大原则之依赖倒置原则

文章目录 概念逻辑关系 小结 概念 依赖倒置原则指在设计代码架构时&#xff0c;高层模块不应该依赖底层模块&#xff0c;二者都应该依赖抽象。抽象不应该依赖于细节&#xff0c;细节应该依赖于抽象。 逻辑关系 如上图所示&#xff0c;逻辑应该就是这样&#xff0c;高层依赖于…

深度学习-语言模型

深度学习-语言模型 统计语言模型神经网络语言模型语言模型的应用序列模型&#xff08;Sequence Model&#xff09;语言模型&#xff08;Language Model&#xff09;序列模型和语言模型的区别 语言模型&#xff08;Language Model&#xff09;是自然语言处理&#xff08;NLP&…

web自动化-数据驱动与失败用例截图、失败重新运行

因为只有失败的用例需要截图&#xff0c;那么问题就是&#xff1a; 什么时候用例会失败&#xff1f; 数据驱动测试 我们前面覆盖到的用例都是正常的用例&#xff0c;如果要测试异常的用例呢&#xff1f; 我们来写一下登录的异常 场景&#xff1a;【login_page】 # 用户输入框…

Adobe AntiCC 简化版 安装教程

Adobe AntiCC 简化版 安装教程 原文地址&#xff1a;https://blog.csdn.net/weixin_48311847/article/details/139277743