This is how my JSON file looks like. As you can see, the start_x, start_y, and end_x, end_y, degree_of_rotation is a number.
{
"ID" : "ROLL1",
"action" : "start",
"zone" :
{
"start_x" : 0,
"start_y" : 4,
"end_x" : 10,
"end_y" : 5,
"motion" :
{
"motion_type": "xxxxxx",
"degree_of_rotation": 30,
"rotation_direction": "yyyyyy",
"linear_direction": "+ve"
}
}
}
How can I replace and save the number in JSON from the server? Currently, this is what I have. Qt5 has a new JSON parser and I want to use it. The problem is that it isn't too clear about what the functions do
void JsonFileread::Json_File_Function()
{
try
{
qDebug() <<"file reading";
file.setFileName("/home/JSON/jsonfile.js");
file.open(QIODevice::ReadOnly | QIODevice::Text);
QFileDevice::FileError err = QFileDevice::NoError;
if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
qDebug() <<"Could not open file : "<<file.fileName() <<"for reading :"<<file.errorString()<<endl;
errMsg =file.errorString();
err =file.error();
cout<<"err : "<<err<<endl;
}
settings = file.readAll();
if (file.error() != QFile::NoError) {
qDebug() << QString("Failed to read from file %1, error: %2").arg(file.fileName()).arg(file.errorString());
}
if (settings.isEmpty()) {
qDebug() << "No data was currently available for reading from file" << file.fileName();
}
file.close();
object = EchoClient::jsonstringflag;
QJsonDocument sd = QJsonDocument::fromJson(settings.toUtf8());
QJsonObject sett2 = sd.object();
QJsonValue mainid = sett2["ID"];
mainid = mainid.toString();
QJsonValue action = sett2["action"];
actionstring = action.toString();
QJsonValue value = sett2.value(QString("zone"));
QJsonObject item = value.toObject();
QJsonValue startx = item["start_x"];
startvaluex = startx.toInt();
QJsonValue starty = item["start_y"];
startvaluey = starty.toInt();
QJsonValue endx = item["end_x"];
endvaluex = endx.toInt();
xendvaluestring = endx.toString();
qWarning() << endvaluex<<endl;
QJsonValue endy = item["end_y"];
endvaluey = endy.toInt();
yendvaluestring = endy.toString();
qWarning() << endvaluey<<endl;
QJsonValue motion = item.value(QString("motion"));
QJsonObject motion_object = motion.toObject();
QJsonValue motiontype = motion_object["motion_type"];
motiontypestring = motiontype.toString();
QJsonValue directionlinear = motion_object["linear_direction"];
lineardirection = directionlinear.toString();
QJsonValue rotatingangle = motion_object["degree_of_rotation"];
angleofrotation = rotatingangle.toInt();
}
catch (QJsonParseError error)
{
qDebug() << error.errorString();
}
catch(...)
{
qDebug() << "due to some other error";
}
}
So help to solve the problem
You can write to a QJsonObject very similar to how you read its properties
QJsonObject obj;
obj["key"] = value;
Once you have built the QJsonObject tree, set the top level element on a QJsonDocument and use it to generate the JSON content.
Related
What should i do to get output for example: Bid value is 2248.48?
Here is code:
QNetworkRequest request = QNetworkRequest(QUrl("https://api.30.bossa.pl/API/GPW/v2/Q/C/_cat_name/WIG20?_t=1637005413888"));
QNetworkReply* reply = m_manager.get(request);
QObject::connect(reply, &QNetworkReply::finished, [reply]() {
QByteArray rawData = reply->readAll();
QString textData(rawData);
// qDebug() << textData;
QJsonDocument doc = QJsonDocument::fromJson(textData.toUtf8());
auto rootObj = doc.object();
auto _d = rootObj.value("_d").toArray();
auto _t = _d[0].toObject().value("_t").toArray();
auto _quote = _t[0].toObject().value(QString("_quote"));
qDebug() << _quote;
eply->deleteLater();
Now i get QJsonValue (string, "2248.48)
when i tried this:
QJsonObject root = _t[0].toObject().value(QString("_quote"));
qDebug() << root;
QJsonValue value = obj.value(QString("_quote"));
qDebug() << "Bid value is" << value.toString();;
https://api.30.bossa.pl/API/GPW/v2/Q/C/_cat_name/WIG20?_t=1637005413888
{"message":"OK","_quote_date":null,"_type":"C","_symbol":["WIG20"],"_d":[{"_h":"Własne - 22 listopada 2021 16:42","_hs":"Własne","_max_quote_dtm":"22 listopada 2021","_max_quote_dtm_lc":"22 listopada, 16:42","_ret_quote_dtm":"2021-11-22","_t":[{"_symbol":"WIG20","_symbol_short":"WIG20","_group":"X1","_isin":"PL9999999987","_quote_date":"2021.11.22","_quote_time":"16:42","_time":"16:42","_phase":"Sesja","_quote_max":"2262.74","_quote_min":"2237.64","_quote_open":"2251.08","_quote_ref":"2248.18","_quote_imp":"2254.37","_bid_size":null,"_bid_volume":null,"_bid_orders_nr":null,"_ask_size":null,"_ask_volume":null,"_ask_orders_nr":null,"_volume":null,"_open_positions":null,"_quote_volume":null,"_transactions_nr":null,"_turnover_value":841977698,"_quote":"2254.10","_step":"2","_type_of_instrument":"0","_settlement_price":null,"_change_proc":0.26,"_change_pnts":5.9200,"_30d_change_max":2449.6400,"_30d_change_min":2221.6800,"_change_type":"_change_proc","_quote_type":"_quote","_debut":"0","_live":"1","_sw_symbol_short":0,"_is_indice":"1","_change":"+0.26","_change_suffix":"%","_change_max_min":"+1.12","_change_close_open":"+0.13","_change_settl_ref":null}]}],"_i":[null],"_count":1,"_d_fx":{"_h":null,"_hs":null,"_max_quote_dtm":null,"_max_quote_dtm_lc":null,"_t":[]}}
I got erros "QJsonValue to non-scalar type QJsonObject requested"
You either want _quote.toString() (first listing) or root.toString() (second listing)
I have a Json file to read and display on UI. Reading is fine but when I tried to update value wheelbase, code runs with no errors but it does not update the Json
Json file example
{
"$type": "SystemList",
"$values": [
{
"chassicId": 1000,
"wheelbase": 98
},
{
"chassicId": 1001,
"wheelbase": 102
}
]
}
This is the write function. What I have tried is to parse the Json file to the QJsonArray, then iterates and map with the function id parameter in order to update the wheelbase value.
void updateWheelbase(const int& id)
{
updatedWheelbase = dialog.wheelbaseInput().toDouble();
QFile file("json file path");
file.open(QIODevice::ReadOnly | QIODevice::Text);
QByteArray jsonData = file.readAll();
file.close();
QJsonDocument itemDoc = QJsonDocument::fromJson(jsonData);
QJsonObject rootObject = itemDoc.object();
QJsonArray valuesArray = rootObject.value("$values").toArray();
//get a copy of the QJsonObject
QJsonObject obj;
for (auto v: valuesArray) {
QJsonObject o = v.toObject();
if (o.value("chassicId").toInt() == id) {
obj = o;
break;
}
}
// modify the object
obj["wheelbase"] = updatedWheelbase;
int position = 0;
// erase the old instance of the object
for (auto it = valuesArray.begin(); it != valuesArray.end(); ++it) {
QJsonObject obj = (*it).toObject();
if (obj.value("chassicId").toInt() == id) {
valuesArray.erase(it);
//assign the array copy which has the object deleted
rootObject["$value"] = valuesArray;
break;
}
position++;
}
// add the modified QJsonObject
valuesArray.append(obj);
// replace the original array with the array containing our modified threshold object
itemDoc.setObject(rootObject);
file.open(QFile::WriteOnly | QFile::Text | QFile::Truncate);
file.write(itemDoc.toJson());
file.close();
}
You should place rootObject["$value"] = valuesArray; after the valuesArray.append(obj);. In your example, when append obj to valuesArray, you just update valuesArray, have not update rootObject.
#include <QtWidgets/QApplication>
#include <QDebug>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
void updateWheelbase()
{
int id = 1001;
double updatedWheelbase = 1.1;
QFile file("./Debug/a.json");
file.open(QIODevice::ReadOnly | QIODevice::Text);
QByteArray jsonData = file.readAll();
file.close();
QJsonDocument itemDoc = QJsonDocument::fromJson(jsonData);
QJsonObject rootObject = itemDoc.object();
QJsonArray valuesArray = rootObject.value("$values").toArray();
//get a copy of the QJsonObject
QJsonObject obj;
for (auto v : valuesArray) {
QJsonObject o = v.toObject();
if (o.value("chassicId").toInt() == id) {
obj = o;
break;
}
}
// modify the object
obj["wheelbase"] = updatedWheelbase;
int position = 0;
// erase the old instance of the object
for (auto it = valuesArray.begin(); it != valuesArray.end(); ++it) {
QJsonObject obj = (*it).toObject();
if (obj.value("chassicId").toInt() == id) {
valuesArray.erase(it);
//assign the array copy which has the object deleted
rootObject["$values"] = valuesArray;
break;
}
position++;
}
// add the modified QJsonObject
valuesArray.append(obj);
rootObject["$values"] = valuesArray;
// replace the original array with the array containing our modified threshold object
itemDoc.setObject(rootObject);
file.open(QFile::WriteOnly | QFile::Text | QFile::Truncate);
file.write(itemDoc.toJson());
file.close();
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
updateWheelbase();
return a.exec();
}
I have an object that I serialize it into JSON using the code below (also see the the struct):
struct RegisterItem {
RegisterType Type = RegisterType::ReadWrite;
QString Name = QStringLiteral("REGISTER");
int Bank = 0;
int Address = 0;
int Range = 1;
int DefaultValue = 0;
int CurrentValue = 0;
int SpecialAction = REG_SPECIAL_ACTION_NONE;
};
This code converts it to json text file:
bool saveRegisterStateToFile(const QVector<RegisterWidget*>& widgets)
{
QJsonArray arr;
for(int i = 0; i < widgets.size(); i++) {
RegisterItem item = widgets[i]->registerItem();
auto data = QJsonObject({
qMakePair(QString("Address"), QJsonValue(item.Address)),
qMakePair(QString("Name"), QJsonValue(item.Name)),
qMakePair(QString("Bank"), QJsonValue(item.Bank)),
qMakePair(QString("Type"), QJsonValue(static_cast<int>(item.Type))),
qMakePair(QString("DefaultValue"), QJsonValue(item.DefaultValue)),
qMakePair(QString("SpecialAction"), QJsonValue(item.SpecialAction))
});
arr.push_back(data);
}
QFile file("json.txt");
file.open(QFile::WriteOnly);
file.write(QJsonDocument(arr).toJson());
}
This all works fine and produces the json file...it looks like this (first few lines):
[
{
"Address": 0,
"Bank": 0,
"DefaultValue": 0,
"Name": "V_ADC_IN",
"SpecialAction": 0,
"Type": 3
},
{
"Address": 1,
"Bank": 0,
"DefaultValue": 0,
"Name": "V_ADC_SCALE",
"SpecialAction": 0,
"Type": 3
},
{
"Address": 2,
"Bank": 0,
Now, I need to do the reverse...but my json object size is always 0! what is the problem?
QFile file(url);
file.open(QIODevice::ReadOnly | QIODevice::Text);
QString raw = file.readAll();
file.close();
QJsonDocument doc = QJsonDocument::fromJson(raw.toUtf8());
QJsonObject obj = doc.object();
QJsonArray arr = obj[""].toArray();
Your objects does not have an identifier...so you need to access by position in the array. Something like this:
QJsonDocument doc = QJsonDocument::fromJson(raw.toUtf8());
QJsonArray arr = doc.array(); // get array representation of the doc
for(int i = 0; i < arr.size(); i++) {
QJsonValue val = arr.at(i);
// The following line should thoritically prin the Name field
qDebug() << val.toObject().value("Name");
}
I want to read some data from a file with QT and then show data in a QTableWidget through a QComboBox.
void DemoDataView::on_comboBox_activated(const QString &arg1)
{
ui->tableWidget->setColumnCount(5);
ui->tableWidget->setRowCount(21);
ui->tableWidget->verticalHeader()->setVisible(false);
ui->tableWidget->setHorizontalHeaderLabels(QString("Age Range ; Male Population ; Male Percentage ; Female Population ; Female Percentage").split(";"));
ui->tableWidget->resizeColumnsToContents();
ui->tableWidget->resizeRowsToContents();
QFile inputFile("./data.txt");
if(!inputFile.open(QIODevice::ReadOnly))
{
QMessageBox::information(0, "Error", inputFile.errorString());
}
QTextStream in(&inputFile);
int rows = 0;
while(!in.atEnd()) {
QString mLine = in.readLine();
QStringList fields = mLine.split(" ");
QStringList::iterator it = fields.begin();
QString regName = *it;
ui->label->setText(arg1);
if(regName != "<END>" && QString::compare(regName, arg1) == 0) {
ui->label->setText(regName);
it++;
QString ageRange = *it;
it++;
QString nMale = *it;
double male = nMale.toDouble();
it++;
QString nFemale = *it;
double female = nFemale.toDouble();
ui->tableWidget->setItem(rows, 0, new QTableWidgetItem(ageRange));
ui->tableWidget->setItem(rows, 1, new QTableWidgetItem(nMale));
ui->tableWidget->setItem(rows, 3, new QTableWidgetItem(nFemale));
ui->tableWidget->setItem(rows, 2, new QTableWidgetItem(malePercCalc(male, female)));
ui->tableWidget->setItem(rows, 4, new QTableWidgetItem(femalePercCalc(male, female)));
rows++;
}
inputFile.close();
}
}
The file is in both the project folder and the build project folder.
When I run the application everything works good but in the Application Output tab I have this error message:
"QIODevice:: read (QFile, "./data.txt"): device not open"
Every time I click on a QComboBox item.
If it can be useful, this is the filling code of the QComboBox:
void DemoDataView::setComboBoxRegion() {
QFile inputFile("./data.txt");
if(!inputFile.open(QIODevice::ReadOnly))
{
QMessageBox::information(0, "Error", inputFile.errorString());
}
QTextStream in(&inputFile);
while(!in.atEnd()) {
QString mLine = in.readLine();
QStringList fields = mLine.split(" ");
QStringList::iterator it = fields.begin();
QString regName = *it;
if(regName != "<END>") {
if(ui->comboBox->findText(regName) == -1){
ui->comboBox->addItem(regName);
}
}
}
inputFile.close();
}
Your problem is that you are calling:
inputFile.close();
INSIDE of your loop, which means it is closed in the first loop. I can't really think of any cases that this would be the desired thing to happen;
To solve this, you should move it to the outside of the loop.
I'm trying to find a solution that in case that a validation is not successful because there is more then one error in the XML file the Qt MessageHandler(line, column, description etc. ) is able to show every error in the XML data not just the first one that occurs in the XML file.
Example:
I have an error in line: 65 (see pic)
but there are also errors in line :78,83,95 but it dose not show it only shows the first one.
Is there a solution for this case? And if yes how?
My Code looks like this:
MessageHandler messageHandler;
QFile xsdfile("....xsd");
xsdfile.open(QIODevice::ReadOnly);
QXmlSchema schema;
schema.setMessageHandler(&messageHandler);
bool errorOccurred = false;
if (schema.load(&xsdfile, QUrl::fromLocalFile(xsdfile.fileName())) == false)
errorOccurred = true;
else
{
QXmlSchemaValidator xmlvalidator(schema);
QFile xmlfile("......xml");
xmlfile.open(QIODevice::ReadOnly);
if (!xmlvalidator.validate(&xmlfile, QUrl::fromLocalFile(xmlfile.fileName())))
errorOccurred = true;
xmlfile.close();
}
xsdfile.close();
if (errorOccurred) {
QString qs = messageHandler.statusMessage();
cout << "Line: " << messageHandler.line() << "\n" << "Row: " << messageHandler.column() << "\n" << "ErrorMessage: ";
std::cout << qs.toUtf8().constData() << std::endl;
return -1;
}
else {
return 0;
}
And my MessageHandler class looks like this:
class MessageHandler : public QAbstractMessageHandler
{
public:
MessageHandler()
: QAbstractMessageHandler(0)
{
}
QString statusMessage() const
{
return m_description;
}
int line() const
{
return m_sourceLocation.line();
}
int column() const
{
return m_sourceLocation.column();
}
protected:
virtual void handleMessage(QtMsgType type, const QString &description,
const QUrl &identifier, const QSourceLocation &sourceLocation)
{
Q_UNUSED(type);
Q_UNUSED(identifier);
m_description = description;
m_sourceLocation = sourceLocation;
}
private:
QString m_description;
QSourceLocation m_sourceLocation;
};
Thanks :)
I think you need to write a custom validator to catch all errors. You can modify this example code to catch all errors.
struct NodeProperties
{
NodeProperties()
{
values.resize(names.size());
}
std::vector<int> values;
static QStringList names;
static QString rootName;
static QString childName;
};
QString NodeProperties::rootName = "static_route";
QString NodeProperties::childName = "molenet";
QStringList NodeProperties::names = QList<QString>() << "node_id"
<< "nextHop_id"
<< "sink_id"
<< "delay_before_send"
<< "delay_before_sleep";
QList<NodeProperties> nodesProperties;
bool parseXMLFile()
{
QXmlStreamReader xmlStreamReader;
QString xmlFile;
xmlFile = QFileDialog::getOpenFileName(this,
tr("Open XML file"), QDir::currentPath(), tr("XML (*.xml)"));
if(xmlFile.isEmpty())
return false;
QFile file(xmlFile);
if (!file.open(QFile::ReadOnly | QFile::Text))
{
QMessageBox::warning(this,tr("Error: Cannot read file ..."),
(xmlFile+" " + file.errorString() ));
return false;
}
nodesProperties.clear();
xmlStreamReader.setDevice(&file);
xmlStreamReader.readNext();
while(!xmlStreamReader.atEnd())
{
if(xmlStreamReader.isStartElement())
{
if(xmlStreamReader.name() == NodeProperties::rootName)
xmlStreamReader.readNext();
if(xmlStreamReader.name() == NodeProperties::childName)
{
xmlStreamReader.readNext();
if(xmlStreamReader.isCharacters() )
xmlStreamReader.readNext();
if(xmlStreamReader.isStartElement())
{
NodeProperties prop;
for(int i = 0; i < NodeProperties::names.size(); ++i)
{
if(xmlStreamReader.isCharacters() )
{
xmlStreamReader.readNext();
--i;
continue;
}
if(xmlStreamReader.name() == NodeProperties::names[i])
{
prop.values[i] = xmlStreamReader.readElementText().toInt();
}
xmlStreamReader.readNext();
}
nodesProperties.push_back(prop);
}
}
}
xmlStreamReader.readNext();
}
file.close();
if (xmlStreamReader.hasError())
{
QMessageBox::warning(this,tr("Error: Failed to parse file "),
(xmlFile+" " + xmlStreamReader.errorString() ));
nodesProperties.pop_back();
}
else if (file.error() != QFile::NoError)
{
qDebug() << "Error: Cannot read file " << qPrintable(xmlFile)
<< ": " << qPrintable(file.errorString());
}
//createGraphVizFile(xmlFile);
this->xmlFile = xmlFile;
return true;
}
The XML file is:
<?xml version="1.0"?>
<static_route>
<molenet>
<node_id> 1 </node_id>
<nextHop_id> 2 </nextHop_id>
<sink_id> 254 </sink_id>
<delay_before_send> 2 </delay_before_send>
<delay_before_sleep> 30 </delay_before_sleep>
</molenet>
<molenet>
<node_id> 2 </node_id>
<nextHop_id> 3 </nextHop_id>
<sink_id> 254 </sink_id>
<delay_before_send> 4 </delay_before_send>
<delay_before_sleep> 30 </delay_before_sleep>
</molenet>
</static_route>