🎩 欢迎来到技术探索的奇幻世界👨💻
📜 个人主页:@一伦明悦-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,并包含了一些成员变量、成员函数以及信号与槽函数。代码解释如下:
-
头文件包含部分:
- 通过
#pragma once
和#ifndef...#endif
语句来确保头文件只被包含一次,避免重复定义。 - 包含了一系列需要使用的头文件,例如 Qt 相关的头文件、第三方库的头文件等。
- 通过
-
命名空间:
- 使用
namespace Ui
包含了一个名为Dialog_con
的类的声明。
- 使用
-
Dialog_con 类:
- 公有成员函数:定义了类的公有成员函数,例如构造函数、析构函数以及处理网络请求的函数。
- 成员变量:定义了一系列成员变量,包括各种配置信息、JSON 数据解析相关的变量,以及结构体
hdgl_predict_data
和其他结构体变量。 - 私有成员函数:定义了一些私有函数用于处理内部逻辑,如解析 JSON 数据、将字节转换为浮点数等。
- 槽函数:定义了一系列槽函数,对应不同的按钮点击事件,如发送 GET 请求、发送 POST 请求、配置参数等。
- 信号:定义了一个信号
showmain()
,可以在需要时发射信号。
-
结构体:
- 定义了一个名为
hdgl_predict_data
的结构体,包含了预测数据的各个字段。 - 其他结构体变量用于存储不同类型的测量数据。
- 定义了一个名为
-
函数实现:
- 实现了一些函数,包括将字节数组转换为浮点数、解析 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 文件数据的方式具有高效、稳定和可靠的特点,能够帮助开发者快速地实现网络数据的获取和处理,提高开发效率和用户体验。