How to write/Read Json file - c++

I have written a program in C++, Now, I can read the JSON file and I can able to execute the instructions. Here I have attached Sample JSON file (Pre defined), As per the Json instruction program will execute, when it will reach the end coordinate the program will stop.
For starting and stopping string received from the server through web socket. If the start button clicked from server, application will start, In Json file I have defined the mapping coordinate start_x, start_y when it will reach the end_x, end_y coordinate the application will stop.
Now, I want to sent the start_x, start_y, end_x, end_y coordinate from server. Whenever the coordinate values are coming from server that should update (Change/Write) the coordinate values in JSON, not only values, whatever the string sending from server. I know how to read JSON and execute the instruction, I don't know how to write, replace, update JSON from server. Then I want to execute the instructions.
Jsonfile.js
{
"ID" : "NO1",
"action" : "start",
"zone" :
{
"start_x" : 0,
"start_y" : 4,
"end_x" : 10,
"end_y" : 5,
"motion" :
{
"motion_type": "Linear",
"degree_of_rotation": 30,
"rotation_direction": "clock",
"linear_direction": "+ve"
}
}
}
Jsonfileread.cpp
qDebug() <<"file reading";
file.setFileName("/PROJECT/JSON/jsonfile.js");
file.open(QIODevice::ReadOnly | QIODevice::Text);
if (!file.exists()){
cout<<"file found"<<endl;
}
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();
QJsonValue endy = item["end_y"];
endvaluey = endy.toInt();
yendvaluestring = endy.toString();
Kindly assist me to solve this issue.

Related

QT 6: "Exception thrown: read access violation e was 0xFFFFFFFFFFFFFFF7" when trying to read Json from a file

I am trying to read Json from a file, that I have previously created using QT, so it should be proper Json. Furthermore I have already implemented such a functionality in another program of mine, in which it worked fine and still works, so I basically copied the functions into the new program, but now I am recieving a weird error and cant fix it.
Error: "Exception thrown: read access violation.
e was 0xFFFFFFFFFFFFFFF7."
kegelbuch.cpp(void Kegelbuch::load(QString path):
void Kegelbuch::load(QString path, QString tab) {
//Load json file
Datastream* loadStream = new Datastream;
QJsonObject data = loadStream->loadData(path); //Error
if (data.contains("KeglerFullName") && data["KeglerFullName"].isArray()) {
QJsonArray keglerFullName = data["KeglerFullName"].toArray();
for (auto fullName : keglerFullName) {
if (fullName.isString()) {
QLineEdit* fullNameEdit = new QLineEdit;
fullNameEdit->setText(fullName.toString());
ui.keglerTab->layout()->addWidget(fullNameEdit);
}
}
}
else if (data.contains("KeglerShortName") && data["KeglerShortName"].isArray()) {
QJsonArray keglerShortName = data["KeglerShortName"].toArray();
for (auto shortName : keglerShortName)
{
if (shortName.isString()) {
QLineEdit* shortNameEdit = new QLineEdit;
shortNameEdit->setText(shortName.toString());
ui.keglerTab->layout()->addWidget(shortNameEdit);
}
}
}
}
datastream.cpp(const QJsonObject& Datastream::loadData(QString path)):
const QJsonObject& Datastream::loadData(QString path) {
QFile loadFile(saveFormat == Json
? QStringLiteral("data.json")
: QStringLiteral("data.dat"));
if (!loadFile.open(QIODevice::ReadOnly)) {
qWarning("Couldn't find/open the save file.");
QJsonObject returnObject;
return returnObject;
}
QByteArray saveData = loadFile.readAll();
QJsonDocument loadDoc(saveFormat == Json
? QJsonDocument::fromJson(saveData)
: QJsonDocument(QCborValue::fromCbor(saveData).toMap().toJsonObject()));
return loadDoc.object();
}
data.json
{
"KeglerFullName": [
"sadfg",
"ftzjtzc",
"restes",
"sxrtfgh"
],
"KeglerShortName": [
"waf",
"drxht",
"dsfgh",
"dft"
]
}
Thanks!

How to parse this JSON wit Qt an C++?

I have a json like this:
{
"name1": {
"path": "D:/myfolder"
},
"name2": {
"path": "D:/anotherFolder"
},
"name3": {
"path": "D:/myfolder"
}
}
And I want to get: are the names and the folder names.
like :
name1, D:/myfolder
name2, D:/anotherFolder
name3, D:/myfolder
It is not important if i get them independently or in an map, because i want to save them
to new variables into another struct.
what I have so far is:
QString jsonFile = "myjson.json";
QFile loadFile(jsonFile);
if(!loadFile.open(QIODevice::ReadOnly)){
qDebug() << "Failed to open " << loadFile; }
QByteArray data = loadFile.readAll();
QJsonDocument loadDoc(QJsonDocument::fromJson(data));
QJsonObject json = loadDoc.object();
QStringList keys = json.keys(); // <------- that give me the names. check.
But i didnt get it: how to get the second element?!?
the nearest approche so far was to get the "2nd dimension" with foreach:
foreach(const QJsonValue path, json ){
qInfo() << path;
}
this gave me as output:
QJsonValue(object, QJsonObject({"path": "D:/myfolder"}))
QJsonValue(object, QJsonObject({"path": "D:/anotherFolder"}))
QJsonValue(object, QJsonObject({"path": "D:/myfolder"}))
Most optimal way to do it just using single for iteration
QJsonDocument doc = QJsonDocument::fromJson(data);
QJsonObject json = doc.object();
for (auto it = json.constBegin(); it != json.constEnd(); ++it)
{
qInfo() << it.key() << it.value().toObject().value("path").toString();
}
You have to iterate through the keys obtaining the value, and then access the last one using the key "path":
QJsonDocument loadDoc = QJsonDocument::fromJson(data);
QJsonObject json = loadDoc.object();
for(const QString & key : json.keys()){
qInfo() << key << json[key].toObject()["path"].toString();
}

How to append json data into existing json file in Qt

I am creating .json file and I'm trying to append new data into json file. For that I call append file instead of writeonly file but get error at console "Error loading JSON: "garbage at the end of the document" # 548" How to append json file?
/*-------------Write data into files ------------*/
void addLogs(QString flightType, QString flightTextLogs){
QFile file("FlightNotifications.json"); // json file
file.open(QFile::WriteOnly ); // Append
QJsonObject m_projectDetails;
qint64 qiTimestamp=QDateTime::currentMSecsSinceEpoch();
QDateTime dt;
dt.setTime_t(qiTimestamp/1000);
m_projectDetails.insert("Type", flightType);
m_projectDetails.insert("TextLog", flightTextLogs);
m_projectDetails.insert("Date and Time",dt.toString("yyyy-MM-dd hh:mm:ss"));
rootObject.insert("Notifications",m_projectDetails);
rootObject1.append(rootObject);
QJsonDocument doc1(rootObject1);
file.write(doc1.toJson());
file.close();
}
/*--------------- Read json file-----------------*/
void readFlightLogs(){
qDebug()<<"Read data";
QByteArray val;
QFile file("FlightNotifications.json");
if(file.exists())
{
file.open(QIODevice:: ReadOnly | QIODevice::Text);
val = file.readAll();
file.close();
QJsonParseError jspe{};
const QJsonDocument doc = QJsonDocument::fromJson(val, &jspe);
if (doc.isNull())
{
qWarning() << "Error loading JSON:" << jspe.errorString() << "#" << jspe.offset;
}
QJsonArray jsonArray = doc.array();
if(jsonArray.size()<1)
{
}
for (int i=0; i < jsonArray.size(); i++)
{
QJsonObject temp = jsonArray.at(i).toObject();
FlightNotificationList ::getInstance()-> addAsset(temp.value("Notifications").toObject().value("Type").toString(),
temp.value("Notifications").toObject().value("TextLog").toString(),
temp.value("Notifications").toObject().value("Date and Time").toString(),
"name");
qDebug() << temp.value("Notifications").toObject().value("Type").toString();
qDebug() << temp.value("Notifications").toObject().value("TextLog").toString();
qDebug() << temp.value("Notifications").toObject().value("Date and Time").toString();
}
}
}
When I use QFile::WriteOnly the file gets override. How to append .json file
You should load the whole json array content, insert new item then rewrite the json array to disk.
The addLogs function could be rewritten as :
/*-------------Write data into files ------------*/
bool addLogs(QString flightType, QString flightTextLogs){
QFile file("FlightNotifications.json"); // json file
if( !file.open( QIODevice::ReadOnly ) ) //read json content
{
//open file error ...
return false;
}
QJsonDocument jsonOrg = QJsonDocument::fromJson( file.readAll() );
file.close();
//local variable, do not use m_ prefix.
QJsonObject projectDetails = { {"Type", flightType},
{"TextLog", flightTextLogs},
{"Date and Time", QDateTime::currentDateTime().toString( "yyyy-MM-dd hh:mm:ss" )} };
QJsonObject notificationObj = {{ "Notifications", projectDetails }};
QJsonArray arrLog = jsonOrg.array();
arrLog.push_back( notificationObj );
QJsonDocument doc( arrLog );
if( !file.open( QIODevice::WriteOnly ) ) //write json content to file.
{
//cannot open for write ...
return false;
}
file.write(doc.toJson());
file.close();
return true;
}
you should open the file in append mode too: (QIODevice::Append)
myFile.open(QIODevice::WriteOnly | ... | QIODevice::Append)

Can't get a value from LMDB

I'm trying to store and fetch some data from LMDB. Data seems to be stored, I can see the keys in my database, but it gives me MDB_NOTFOUND when I try to fetch the value with the same ID I have just stored it under.
Database opening
MDB_env* environment;
MDB_dbi main;
MDB_dbi order;
mdb_env_create(&environment);
mdb_env_set_maxdbs(environment, 2);
mdb_env_open(environment, path.toStdString().c_str(), 0, 0664);
int rc;
MDB_txn *txn;
mdb_txn_begin(environment, NULL, 0, &txn);
mdb_dbi_open(txn, "main", MDB_CREATE, &main);
mdb_dbi_open(txn, "order", MDB_CREATE | MDB_INTEGERKEY, &order);
mdb_txn_commit(txn);
Insertion
void Core::Archive::addElement(const Shared::Message& message) {
QByteArray ba;
QDataStream ds(&ba, QIODevice::WriteOnly);
message.serialize(ds);
uint64_t stamp = message.getTime().toMSecsSinceEpoch();
const std::string& id = message.getId().toStdString();
MDB_val lmdbKey, lmdbData;
lmdbKey.mv_size = id.size();
lmdbKey.mv_data = (uint8_t*)id.c_str();
lmdbData.mv_size = ba.size();
lmdbData.mv_data = (uint8_t*)ba.data();
MDB_txn *txn;
mdb_txn_begin(environment, NULL, 0, &txn);
int rc;
rc = mdb_put(txn, main, &lmdbKey, &lmdbData, 0);
if (rc == 0) {
MDB_val orderKey;
orderKey.mv_size = 8;
orderKey.mv_data = (uint8_t*) &stamp;
rc = mdb_put(txn, order, &orderKey, &lmdbKey, 0);
if (rc) {
mdb_txn_abort(txn);
} else {
rc = mdb_txn_commit(txn);
if (rc) {
qDebug() << "A transaction error: " << mdb_strerror(rc);
}
}
} else {
qDebug() << "An element couldn't been added to the archive, skipping" << mdb_strerror(rc);
mdb_txn_abort(txn);
}
}
Fetching
Shared::Message Core::Archive::getElement(const QString& id) {
MDB_val lmdbKey, lmdbData;
lmdbKey.mv_size = id.toStdString().size();
lmdbKey.mv_data = (uint8_t*)id.toStdString().c_str();
MDB_txn *txn;
int rc;
mdb_txn_begin(environment, NULL, MDB_RDONLY, &txn);
rc = mdb_get(txn, main, &lmdbKey, &lmdbData);
if (rc) {
qDebug() <<"Get error: " << mdb_strerror(rc);
mdb_txn_abort(txn);
throw NotFound(id.toStdString(), jid.toStdString());
} else {
//it never comes here
}
}
Testing code
Core::Archive ar();
ar.open("Test");
Shared::Message msg1;
msg1.generateRandomId();
msg1.setBody("oldest");
msg1.setTime(QDateTime::currentDateTime().addDays(-7));
Shared::Message msg2;
msg2.generateRandomId();
msg2.setBody("Middle");
msg2.setTime(QDateTime::currentDateTime().addDays(-4));
Shared::Message msg3;
msg3.generateRandomId();
msg3.setBody("newest");
msg3.setTime(QDateTime::currentDateTime());
ar.addElement(msg2);
ar.addElement(msg3);
ar.addElement(msg1);
Shared::Message d0 = ar.getElement(msg1.getId());
My logs show stored keys. I can see the required key, I can even compare it with the requested key if I use cursors to scroll over the whole storage, it even shows they are equal, but mdb_cursor_get or mdb_get constantly give me MDB_NOTFOUND. What am I doing wrong?
I got it. No matter what I put into database, I have to read it as a char*
Had to modify fetching code
lmdbKey.mv_data = (uint8_t*)id.toStdString().c_str();
I had to change it to
lmdbKey.mv_data = (char*)id.toStdString().c_str();
and it worked

C++ Qt unable to parse JSON array correctly

I am trying to parse json with Qt but I have no success. This is the ouput that I get from the server:
[{"anni":2019},{"anni":2018},{"anni":2017}]
Where that's generated from this simple php:
header('Content-Type: application/json');
echo json_encode($data);
The $data is an array containing the values you see above. I am using this piece of code in Qt 5.11.2:
void MainWindow::showYears() {
//reply is a QNetworkReply* reply;
if (reply->error() != QNetworkReply::NoError) {
//some error managment
} else {
auto responsedata = reply->readAll();
QJsonArray years = QJsonDocument::fromJson(responsedata).array();
qDebug() << QString{responsedata};
for(const QJsonValue& y : years) {
QJsonObject obj = y.toObject();
//doing "qDebug() << r" shows that r is "" (empty!)
auto r = obj["anni"].toString();
ui->comboBoxP->addItem(r);
}
}
}
What's wrong here?
Please note that qDebug() << QString{responsedata}; prints "[{\"anni\":2019},{\"anni\":2018},{\"anni\":2017}]"
The value for your field anni is an integer. Using the member function toString will not convert it to a string representation. it will return NULL. http://doc.qt.io/qt-5/qjsonvalue.html#toString
Try with: auto r = QString::number(obj["anni"].toInt());