从Qt中的QJsonArray构造QString [英] Construct QString from QJsonArray in Qt
问题描述
尝试从 QJsonArray
的值构造 QString
时,出现以下错误:
错误:将'const QString'传递为'this'参数将丢弃限定符[-fpermissive]
。
Dunno在此代码中我弄错了:
QString< CLASS_NAME> :: getData(QString callerValue){
QString BASE_URL =< URL>;
QString stringToReturn =;
QObject :: connect(manager,& QNetworkAccessManager :: finished,this,[=](QNetworkReply * reply){
QByteArray barr = reply-> readAll();
QJsonParseError jpe ;
QJsonDocument jdoc = QJsonDocument :: fromJson(barr& jpe);
QJsonArray近奇数组= jdoc.array();
foreach(const QJsonValue&jv,onymoussArray){
QJsonObject jo = jv.toObject();
QString s = jo.value(< VALUE>)。toString();
stringToReturn.append(s +,); / *错误:上面的错误来自此行... * /
}
}
);
request.setUrl(QUrl(BASE_URL + callerValue));
manager-> get(request);
return stringToReturn;
}
这是另一个经典的希望世界是同步的问题。您不能那样编码。 getData
方法无法按照您希望的方式编写。 getData
这样会阻塞,这很浪费并且会导致有趣的问题-并非最后一个是可怕的用户体验。
取决于您的应用程序,将有几种可能的修复方法:
-
redo
getData
使用协程和co_yield
的隐式连续传递样式-这是未来,并且只能在最新的编译器上完成,除非您使用诸如此类的技巧 -
redo
getData
采用显式连续传递样式, > -
重做
getData
并在数据可用时发出通知, -
具有一个处理代码进度的显式状态机。
连续传递样式需要最少的变化。还要注意其他修复程序-最值得注意的是,您不应该使用 QNetworkAccessManager
的信号:您只对此查询的结果感兴趣,而不对每个查询感兴趣!捕获 QNetworkAccessManager :: finished
信号仅在您确实有一个中心点可以处理所有或至少最频繁的请求时才有用。在这种情况下,这是一个明智的优化:将第一个连接添加到无连接器的Hiterto对象上会产生几个 malloc
的开销。
void类:: getData(const QString& urlSuffix,std :: function< void(const QString&)> cont){
自动const urlString = QStringLiteral( URL%1)。arg(urlSuffix);
QNetworkRequest请求(QUrl(urlString));
auto * reply = m_manager.get(请求);
QObject :: connect(reply,& QNetworkReply :: finished,this,[=] {
QString result;
auto data = reply-> readAll();
QJsonParseError jpe;
auto jdoc = QJsonDocument :: fromJson(data,& jpe);
auto const同义词= jdoc.array();
用于(auto& value:同义词){
auto object = value.toObject();
auto s = object.value(< VALUE>)。toString();
if(!result.isEmpty())
result.append(QLatin1String(,))
result.append(s);
}
reply-> deleteLater();
cont(结果);
});
}
惰性样式要求使用 getData
可重新启动,并允许连续传递,只要将延续连接到信号即可:
class Class:public QObject {
Q_OBJECT
QString m_cachedData;
QNetworkAccessManager m_manager {this};
Q_SIGNAL void dataAvailable(const QString&);
...
};
QString类:: getData(const QString& urlSuffix){
if(!m_cachedData.isEmpty())
return m_cachedData;
auto const urlString = QStringLiteral( URL%1)。arg(urlSuffix);
QNetworkRequest请求(QUrl(urlString));
auto * reply = m_manager.get(请求);
QObject :: connect(reply,& QNetworkReply :: finished,this,[=] {
m_cachedData.clear();
auto data = reply-> readAll();
QJsonParseError jpe;
自动jdoc = QJsonDocument :: fromJson(data,& jpe);
自动const同义词= jdoc.array();
for(auto& value:同义词){
auto object = value.toObject();
auto s = object.value(< VALUE>)。toString();
if(!m_cachedData.isEmpty ())
m_cachedData.append(QLatin1String(,))
m_cachedData.append(s);
}
reply-> deleteLater();
发出dataAvailable(m_cachedData);
});
return {};
}
状态机将状态转换形式化:
class类:公共QObject {
Q_OBJECT
QStateMachine m_sm {this};
QNetworkAccessManager m_manager {this};
QPointer< QNetworkReply> m_reply;
QState s_idle {& m_sm},s_busy {& m_sm},s_done {& m_sm};
Q_SIGNAL void to_busy();
void getData(const QString&);
...
};
Class :: Class(QObject * parent):QObject(parent){
m_sm.setInitialState(& s_idle);
s_idle.addTransition(this,& Class :: to_busy,& s_busy);
s_done.addTransition(& s_idle);
m_sm.start();
}
void Class :: getData(const QString& urlSuffix){
static char const kInit [] =已初始化;
auto const urlString = QStringLiteral( URL%1)。arg(urlSuffix);
QNetworkRequest请求(QUrl(urlString));
m_reply = m_manager.get(请求);
s_busy.addTransition(reply,& QNetworkReply :: finished,& s_done);
to_busy();
if(!s_done.property(kInit).toBool()){
QObject :: connect(& s_done,& QState :: entered,this,[=] {
QString结果;
自动数据= m_reply-> readAll();
QJsonParseError jpe;
auto jdoc = QJsonDocument :: fromJson(data,& jpe);
auto const同义词= jdoc.array();
表示(自动和值:同义词){
自动对象= value.toObject();
自动s = object.value(< VALUE >)。toString();
if(!result.isEmpty())
result.append(QLatin1String(,))
result.append(s);
}
m_reply-> deleteLater();
});
s_done.setProperty(kInit,true);
}
}
While trying to construct a QString
from values from a QJsonArray
, I get the following error:
error: passing 'const QString' as 'this' argument discards qualifiers [-fpermissive]
.
Dunno where I am getting it wrong in this code:
QString <CLASS_NAME>::getData(QString callerValue) {
QString BASE_URL = "<URL>";
QString stringToReturn = "";
QObject::connect(manager, &QNetworkAccessManager::finished, this, [=](QNetworkReply *reply) {
QByteArray barr = reply->readAll();
QJsonParseError jpe;
QJsonDocument jdoc = QJsonDocument::fromJson(barr, &jpe);
QJsonArray synonymsArray = jdoc.array();
foreach (const QJsonValue &jv, synonymsArray) {
QJsonObject jo = jv.toObject();
QString s = jo.value("<VALUE>").toString();
stringToReturn.append(s + ", "); /* ERROR: The error above is from this line... */
}
}
);
request.setUrl(QUrl(BASE_URL + callerValue));
manager->get(request);
return stringToReturn;
}
This is another classic "I wish the world was synchronous" problem. You can't code that way. The getData
method can't be written the way you want it to be. getData
done that way would block, and that's quite wasteful and can lead to interesting problems - not the last of which is horrible UX.
Depending on your application, there would be several possible fixes:
redo
getData
in implicit continuation-passing style using coroutines andco_yield
- this is the future and can be done only on the most recent compilers unless you use hacks such boost coroutines.redo
getData
in explicit continuation-passing style,redo
getData
in lazy style with notification when data is available,have an explicit state machine that deals with progress of your code.
The continuation-passing style requires the least changes. Note the other fixes too - most notably that you shouldn't be using the QNetworkAccessManager
's signals: you're interested only in results to this one query, not every query! Catching QNetworkAccessManager::finished
signal is only useful if you truly have a central point where all or at least most frequent requests can be handled. In such a case, it's a sensible optimization: there is overhead of several malloc
s to adding the first connection to a hiterto connection-free object.
void Class::getData(const QString &urlSuffix, std::function<void(const QString &)> cont) {
auto const urlString = QStringLiteral("URL%1").arg(urlSuffix);
QNetworkRequest request(QUrl(urlString));
auto *reply = m_manager.get(request);
QObject::connect(reply, &QNetworkReply::finished, this, [=]{
QString result;
auto data = reply->readAll();
QJsonParseError jpe;
auto jdoc = QJsonDocument::fromJson(data, &jpe);
auto const synonyms = jdoc.array();
for (auto &value : synonyms) {
auto object = value.toObject();
auto s = object.value("<VALUE">).toString();
if (!result.isEmpty())
result.append(QLatin1String(", "))
result.append(s);
}
reply->deleteLater();
cont(result);
});
}
The lazy style requires the code that uses getData
to be restartable, and allows continuation-passing as well, as long as the continuation is connected to the signal:
class Class : public QObject {
Q_OBJECT
QString m_cachedData;
QNetworkAccessManager m_manager{this};
Q_SIGNAL void dataAvailable(const QString &);
...
};
QString Class::getData(const QString &urlSuffix) {
if (!m_cachedData.isEmpty())
return m_cachedData;
auto const urlString = QStringLiteral("URL%1").arg(urlSuffix);
QNetworkRequest request(QUrl(urlString));
auto *reply = m_manager.get(request);
QObject::connect(reply, &QNetworkReply::finished, this, [=]{
m_cachedData.clear();
auto data = reply->readAll();
QJsonParseError jpe;
auto jdoc = QJsonDocument::fromJson(data, &jpe);
auto const synonyms = jdoc.array();
for (auto &value : synonyms) {
auto object = value.toObject();
auto s = object.value("<VALUE">).toString();
if (!m_cachedData.isEmpty())
m_cachedData.append(QLatin1String(", "))
m_cachedData.append(s);
}
reply->deleteLater();
emit dataAvailable(m_cachedData);
});
return {};
}
The state machine formalizes the state progression:
class Class : public QObject {
Q_OBJECT
QStateMachine m_sm{this};
QNetworkAccessManager m_manager{this};
QPointer<QNetworkReply> m_reply;
QState s_idle{&m_sm}, s_busy{&m_sm}, s_done{&m_sm};
Q_SIGNAL void to_busy();
void getData(const QString &);
...
};
Class::Class(QObject * parent) : QObject(parent) {
m_sm.setInitialState(&s_idle);
s_idle.addTransition(this, &Class::to_busy, &s_busy);
s_done.addTransition(&s_idle);
m_sm.start();
}
void Class::getData(const QString &urlSuffix) {
static char const kInit[] = "initialized";
auto const urlString = QStringLiteral("URL%1").arg(urlSuffix);
QNetworkRequest request(QUrl(urlString));
m_reply = m_manager.get(request);
s_busy.addTransition(reply, &QNetworkReply::finished, &s_done);
to_busy();
if (!s_done.property(kInit).toBool()) {
QObject::connect(&s_done, &QState::entered, this, [=]{
QString result;
auto data = m_reply->readAll();
QJsonParseError jpe;
auto jdoc = QJsonDocument::fromJson(data, &jpe);
auto const synonyms = jdoc.array();
for (auto &value : synonyms) {
auto object = value.toObject();
auto s = object.value("<VALUE">).toString();
if (!result.isEmpty())
result.append(QLatin1String(", "))
result.append(s);
}
m_reply->deleteLater();
});
s_done.setProperty(kInit, true);
}
}
这篇关于从Qt中的QJsonArray构造QString的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!