How to parse this JSON wit Qt an C++? - 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();
}

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 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)

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());

How to write/Read Json file

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.

Qt: QScriptValueIterator has an extra element

I am trying to read JSON objects using the QScriptValue class in Qt and I've noticed that when iterating over an array I always get an extra element at the end.
Let's say I have a string named value like this:
QString value = "{\"identifier\":\"testID\",
\"params\":[{\"field\":\"filed1:\",
\"datatype\":\"integer\",\"fieldend\":\" \"},{\"field\":\"field2:
\",\"datatype\":\"integer\",\"fieldend\":\" \"}]}";
My code for iteration looks like this:
QScriptValue sc;
QScriptEngine engine;
sc = engine.evaluate("("+value+")");
if(sc.isValid())
{
if(sc.property("params").isArray())
{
QScriptValueIterator it(sc.property("params"));
while(it.hasNext())
{
it.next();
qDebug()<< "field:" << it.value().property("field").toString();
qDebug()<< "datatype:" << it.value().property("datatype").toString();
qDebug()<< "fieldend:" << it.value().property("fieldend").toString();
qDebug()<< "--------------";
}
}
}
The output results with an extra element that has empty values:
field: "field1:"
datatype: "integer"
fieldend: " "
--------------
field: "field2: "
datatype: "integer"
fieldend: " "
--------------
field: ""
datatype: ""
fieldend: ""
--------------
I read the documentation of QScriptValueIterator and it says:
The next() advances the iterator. The name(), value() and flags() functions return the name, value and flags of the last item that was
jumped over
So I changed my iteration accordingly:
while(it.hasNext())
{
it.next();
qDebug() << it.name() << " : " << it.value().toString();
qDebug()<< "--------------";
}
But I get something that I did not expect:
"0" : "[object Object]"
--------------
"1" : "[object Object]"
--------------
"length" : "2"
--------------
Can anyone point out what am I doing wrong here?
Thanks.
I faced the same issue and I added this line after the it.next(); line:
if (it.flags() & QScriptValue::SkipInEnumeration) continue;
You can find more info about it here:
http://developer.qt.nokia.com/doc/qt-4.8/qscriptvalueiterator.html#details