How to load QJsonDocument from a file - c++

Im trying to learn how to use JSON and Qt i have menaged and im having problem getting QJsonDocument from a file.The file opens correctly i can also see file's content with qDebug() but the QJsonDocument created from this file is always empty
if(stdButton==QDialogButtonBox::Ok)
{
qDebug()<<"accept button clicked";
QFile userList;
userList.setFileName("users.json");
userList.open(QIODevice::ReadOnly);
//using this qDebug i'm able to see files content
qDebug()<<QJsonDocument::fromJson(userList.readAll());
//but this QJsonDocument is always empty
QJsonDocument userDoc;
userDoc=QJsonDocument::fromJson(userList.readAll());
if(userDoc.isEmpty())
{
qDebug()<<"userDoc is empty";
}
qDebug()<<userDoc;
accept();
}

//but this QJsonDocument is always empty
QJsonDocument userDoc;
userDoc=QJsonDocument::fromJson(userList.readAll());
That's because there is nothing to read from the file since you have read everything from it in the previous call to readAll().
You can store the data from userList.readAll() and use it repeatedly.
QFile userList;
userList.setFileName("users.json");
userList.open(QIODevice::ReadOnly);
QByteArray data = userList.readAll();
qDebug()<<QJsonDocument::fromJson(data);
QJsonDocument userDoc;
userDoc=QJsonDocument::fromJson(data);

Related

QT c++ QSplitter saveState and restoreState

I have a splitter and I want to save his state in file with JSON.
QJsonObject mainJson;
// here I have to convert QByteArray to QString
mainJson.insert("test", QTextCodec::codecForMib(1015)->toUnicode(ui->splitter->saveState()));
QFile file("test.json");
QTextStream textStream;
file.open(QFile::WriteOnly);
textStream.setDevice(&file);
textStream.setCodec("UTF-8");
textStream << QString(QJsonDocument(mainJson).toJson()).toUtf8();
textStream.flush();
file.close();
But file contains this:
\u0000＀\u0000Ā\u0000Ȁ\u0000Ⰱ\u0000쐀\u0000\u0000Ā\u0000Ȁ
Is that ok? And how to convert this back to QByteArray for ui->splitter->restoreState(...);?
PS: I use code from here
The logic in general is to convert the QByteArray to QString, in this case I prefer to convert it to base64 than to use a codec for unicode to avoid the problems of compression and decompression.
Considering the above, the solution is:
Save:
QJsonObject mainJson;
QByteArray state = spliter->saveState();
mainJson.insert("splitter", QJsonValue(QString::fromUtf8(state.toBase64())));
QFile file("settings.json");
if(file.open(QIODevice::WriteOnly)){
file.write(QJsonDocument(mainJson).toJson());
file.close();
}
Restore:
QJsonDocument doc;
QFile file("settings.json");
if(file.open(QIODevice::ReadOnly)){
doc = QJsonDocument::fromJson(file.readAll());
file.close();
}
if(doc.isObject()){
QJsonObject obj = doc.object();
QByteArray state = QByteArray::fromBase64(obj.value("splitter").toString().toUtf8());
spliter->restoreState(state);
}

Better way to use QDomDocument data as text

I am a newbie, I am creating a XML file in which I need to give CRC value to cross check on server. For this I need QDomDocument data as text. For this I am first creating XML file with fake CRC value. Then I open it with QFile and read all data. Then I split data and calculate data CRC. Now I have to rewrite whole file again. I know it is the worst idea ever to write same file twice but as I am a newbie, I don't know how to do it in better style. Here is my code:-
QDomElement docElem = doc.documentElement();
QFile xmlfile(filename);
if(!xmlfile.open(QIODevice::ReadWrite | QIODevice::Text))
{
qDebug("Can not open file device.");
}
xmlfile.resize(0);
QXmlStreamWriter xw;
xw.setDevice(&xmlfile); //set file to XML writer
xw.setAutoFormatting(true);
xw.setAutoFormattingIndent(4);
xw.writeStartDocument();
xw.writeStartElement(fileID); //fileID as the start element
if(docElem.hasAttributes())
{
xw.writeAttribute("xmlns:xs",docElem.attribute("xmlns:xs"));
xw.writeAttribute("xmlns",docElem.attribute("xmlns"));
}
xw.writeTextElement("Frame_Start_ID","STX");
xw.writeTextElement("Frame_Length","1234");
xw.writeTextElement("Source_Device_Id","CDIS_PIS ");
xw.writeTextElement("Destination_Device_Id","DDNS-SERVER ");
xw.writeTextElement("Frame_Code","I");
xw.writeStartElement("Frame_Data");
//inside frame data
xw.writeTextElement("File_Number","1");
xw.writeTextElement("File_Name","Event");
for(int j=0;j<logFields.count();j++)
{
xw.writeTextElement(logFields.at(j),logData.at(j));
}
xw.writeEndElement();
xw.writeTextElement("CRC","14405904");
xw.writeTextElement("Frame_End_Id","ETX");
xw.writeEndDocument();
xmlfile.flush();
xmlfile.close();
QFile xmlfyle(filename);
xmlfyle.open(QIODevice::ReadWrite | QIODevice::Text);
QString content = (QString)xmlfyle.readAll();
QStringList list1 = content.split("<CRC>");
qDebug() << "Split value = " << list1.at(0);
QByteArray crc_new = crc_o.crc_generate_modbus((unsigned char*)list1.at(0).data(),list1.at(0).size());
xmlfyle.resize(0);
QXmlStreamWriter xw_new;
xw_new.setDevice(&xmlfyle); //set file to XML writer
xw_new.setAutoFormatting(true);
xw_new.setAutoFormattingIndent(4);
xw_new.writeStartDocument();
xw_new.writeStartElement(fileID); //fileID as the start element
if(docElem.hasAttributes())
{
xw_new.writeAttribute("xmlns:xs",docElem.attribute("xmlns:xs"));
xw_new.writeAttribute("xmlns",docElem.attribute("xmlns"));
}
xw_new.writeTextElement("Frame_Start_ID","STX");
xw_new.writeTextElement("Frame_Length","1234");
xw_new.writeTextElement("Source_Device_Id","CDIS_PIS ");
xw_new.writeTextElement("Destination_Device_Id","DDNS-SERVER ");
xw_new.writeTextElement("Frame_Code","I");
xw_new.writeStartElement("Frame_Data");
xw_new.writeTextElement("File_Number","1");
xw_new.writeTextElement("File_Name","Event");
for(int j=0;j<logFields.count();j++)
{
xw_new.writeTextElement(logFields.at(j),logData.at(j));
}
xw_new.writeEndElement();
char tab[10];
sprintf(tab,"%d",crc_new.data());
xw_new.writeTextElement("CRC",QString::fromUtf8(tab));
xw_new.writeTextElement("Frame_End_Id","ETX");
xw_new.writeEndDocument();
xmlfyle.flush();
xmlfyle.close();
can anyone suggest me what could be a better way to do this.Thanks
One version of QXmlStreamWriter constructor accepts a QByteArray and writes into the array instead of an output file.
QXmlStreamWriter Class
So what you can do is; using QXmlStreamWriter, prepare data for your XML in a QByteArray, do whatever you need to do with the CRC inside this data; and when everything is done, write this QByteArray to the output file.

Write QPainterPath to XML

I have a QPainterPath that is being drawn to my QGraphicsScene and I am storing the points of the path as they are drawn into a QList.
My question is how do I now save those points out to an xml ( I assume this would work best ) as they are drawn? My goal is when the app closes, I read that xml, and the path is immediately re-drawn into the scene.
Here is the method I have setup for the writing, which I would call everytime I write a new point to the path.
void writePathToFile(QList pathPoints){
QXmlStreamWriter xml;
QString filename = "../XML/path.xml";
QFile file(filename);
if (!file.open(QFile::WriteOnly | QFile::Text))
qDebug() << "Error saving XML file.";
xml.setDevice(&file);
xml.setAutoFormatting(true);
xml.writeStartDocument();
xml.writeStartElement("path");
// --> no clue what to dump here: xml.writeAttribute("points", ? );
xml.writeEndElement();
xml.writeEndDocument();
}
Or maybe this isn't the best way to go about this?
I think I can handle the reading and re-drawing of the path, but this first part is tricking me up.
You may use binary file:
QPainterPath path;
// do sth
{
QFile file("file.dat");
file.open(QIODevice::WriteOnly);
QDataStream out(&file); // we will serialize the data into the file
out << path; // serialize a path, fortunately there is apriopriate functionality
}
Deserialization is similar:
QPainterPath path;
{
QFile file("file.dat");
file.open(QIODevice::ReadOnly);
QDataStream in(&file); // we will deserialize the data from the file
in >> path;
}
//do sth

Qt: Load HTML source code to string

I have an HTML file stored locally that I have to extract text from.
Now I managed to prompt the user for the location and display the HTML file in a QTextBrowser by pressing a button. Now from what I understand the next step would be to convert to a string to be able to search for text inside the source code.
Here's my Button_clicked method so far
void MainWindow::on_getHTMLButton_clicked()
{
QString filename = openFilenameDialog();
if (filename.isEmpty())
{
QMessageBox::information(this, tr("File Name"), "Es wurde keine gültige Datei angegeben.");
}
else
{
QFile file(filename);
if (!file.open(QIODevice::ReadOnly))
{
QMessageBox::information(0, "Info", file.errorString());
}
else
{
QTextStream in(&file);
ui->textBrowserHTML->setText(in.readAll());
}
}
}
The HTML file shows in textBrowser without any issues.
My understanding so far is that I need to create a string to search for a substring in the source code.
Now my problem is that I cannot seem to create a string object with the source of the HTML file as content.
Something like
QString string = in.readAll();
does not seem to work...
I had to learn that after having read out the stream and putting it to the ui by
ui->textBrowserHTML->setText(in.readAll());
the stream is empty – so when I attempt to to do a readAllagain it results in an empty string.

Qt parsing json using network response binary

Alright, I found something I just don't understand. I am making a request to a web service using QtNetworkManager. For some reason I can't seem to go from the network response to a jsondoc directly, I have to cast it into a string and then BACK into uft8?
void WebAPIengine::handleNetworkData(QNetworkReply *networkReply)
{
//No network error
if (!networkReply->error()){
//Cast to string
QString strReply = (QString)networkReply->readAll();
//This works, jsonDoc will have the json response from webpage
QJsonDocument jsonDoc = QJsonDocument::fromJson(strReply.toUtf8());
//This doesn't work, networkReply->readAll() is said to return a QByteArray.
QJsonDocument jsonDoc2 = QJsonDocument::fromBinaryData(networkReply->readAll());
QJsonObject jsonObj = jsonDoc.object();
data = jsonObj;
}
//Network error
else{
data["Error"] = "WebAPIengine::handleNetworkData()";
}
Now I can not understand why jsonDoc is working and jsonDoc2 is not. Can someone explain?
Once you do a QNetworkReply->readAll(), the QNetworkReply object will be empty. So if you call the QNetworkReply->readAll() method again, you will not get anything.
Moreover I don't understand why you are converting the QByteArray returned by QNetworkReply->readAll() into a QString and then converting it back to QByteArray(by calling QString::toUtf8()) to give it to the QJsonDocument::fromJson function.
You can try doing this:
QByteArray temp = newReply->readAll();
QJsonDocument jsonDoc = QJsonDocument::fromJson(temp); // This should work
Also make sure to know what the content of the JSon document is, i.e. if it is a map (QJsonObject), array(QJSonArray), array of maps or map with an array as value.