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");
}
Related
I'm using method PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromString(ConstStringParam data); to parse message in my C++ code. The code is simple as below:
> model::BroadcastMessage msg;
> if(msg.ParseFromString(message.toStdString())){
> qDebug() << "Parse ok"; }else{
> qDebug() << "Parse failed"; }
message is type of QString.
Model is like:
message BroadcastMessage
{
enum BRC_MESSAGE_ID{
StreamURL = 0;
AllStreamURL = 1;
AllSavedURL = 2;
}
BRC_MESSAGE_ID BrcMessageID = 1;
bytes Body = 2;
bool JSON = 3;
string Data = 4;
string Token = 5;
}
message ListAllSavedVideoURL {
repeated LiveVideoURL CurrentUrl = 1;
}
message LiveVideoURL {
string StreamURL = 1;
int32 NumberCurrentViewing = 2;
}
It parses ok when input is short like this:
"\b\u0002\u0012\\\n\u0015\n\u0013saved_x_22-15-34.ts\n\u0015\n\u0013saved_x_22-16-06.ts\n\u0015\n\u0013saved_x_22-16-39.ts\n\u0015\n\u0013saved_x_22-17-04.ts" "" "hoavq.broadcast"
But it fail to parse when data is longger like:
"\b\u0002\u0012?\u0001\n\u0015\n\u0013saved_x_22-15-34.ts\n\u0015\n\u0013saved_x_22-16-06.ts\n\u0015\n\u0013saved_x_22-16-39.ts\n\u0015\n\u0013saved_x_22-17-04.ts\n\u0015\n\u0013saved_x_22-17-38.ts\n\u0015\n\u0013saved_x_22-18-03.ts" "" "hoavq.broadcast"
Both of data having same struct.
Can somebody help me to get working the AutoPageBreak function of Podofo::PdfTable class?
I write so
table1.SetAutoPageBreak(true,
[](PoDoFo::PdfRect &rect, void* pCustom)->PoDoFo::PdfPage*{
PoDoFo::PdfPage *pPage = new PoDoFo::PdfPage(rect,(PoDoFo::PdfStreamedDocument*)pCustom);
rect = PoDoFo::PdfRect(0,0,pPage->GetPageSize().GetWidth(), pPage->GetPageSize().GetHeight());
cout << "qui" << endl;
return pPage;
}, (void*) document);
the function is called correctly but does nothing, the first page is correctly created but the new page is not created.
http://podofo.sourceforge.net/doc/html/classPoDoFo_1_1PdfTable.html#ac33e4bf489d3b7232deae271b8dc552a
the rest of source code is here
document = new PoDoFo::PdfStreamedDocument("doc.pdf");
PoDoFo::PdfPainter painter;
PoDoFo::PdfTable table1 = PoDoFo::PdfTable(2, length);
table1.SetAutoPageBreak(true,
[](PoDoFo::PdfRect &rect, void* pCustom)->PoDoFo::PdfPage*{
PoDoFo::PdfPage *pPage = new PoDoFo::PdfPage(rect,(PoDoFo::PdfStreamedDocument*)pCustom);
rect = PoDoFo::PdfRect(0,0,pPage->GetPageSize().GetWidth(), pPage->GetPageSize().GetHeight());
cout << "qui" << endl;
return pPage;
}, (void*) document);
PoDoFo::PdfSimpleTableModel* tablemodel1 = new PoDoFo::PdfSimpleTableModel(2, length);
PoDoFo::PdfPage* pPage = document->CreatePage(PoDoFo::PdfPage::CreateStandardPageSize(PoDoFo::ePdfPageSize_A4, true));
painter.SetPage(pPage);
PoDoFo::PdfFont* pFont = document->CreateFontSubset("NotoSansMono", false, false, false, PoDoFo::PdfEncodingFactory::GlobalStandardEncodingInstance(), "NotoSansMono-VariableFont_wdth,wght.ttf");
//PoDoFo::PdfFont* pFont = document.CreateFont("Courier");
pFont->SetFontSize(8);
painter.SetFont(pFont);
tablemodel1->SetFont(pFont);
tablemodel1->SetForegroundColor(PoDoFo::PdfColor(0.0, 0.0, 0.0));
tablemodel1->SetBorderEnabled(true);
tablemodel1->SetBorderWidth(0.5);
tablemodel1->SetAlignment(PoDoFo::EPdfVerticalAlignment::ePdfVerticalAlignment_Top);
tablemodel1->SetWordWrapEnabled(true);
painter.DrawTextAligned(20, pPage->GetPageSize().GetHeight()-20, pPage->GetPageSize().GetWidth(), "Riassunto giornaliero risorse", PoDoFo::EPdfAlignment::ePdfAlignment_Center);
string text = "";
vector<OggettoEventoItem*>* listaOggettiEventi;
vector<EventoItem*>* eventoItem;
double rowheight[(int)oggettiSel->size()];
double totrowheight = 0;
for (int i = 0; i < (int)oggettiSel->size(); i++)
{
tablemodel1->SetText(0, i, oggettiSel->at(i)->GetLabel().ToStdString());
for(int j = 0; j < (int)listaOggettiEventi->size(); j++)
{
text += "...";
}
tablemodel1->SetText(1, i, text);
char newline = '\n';
int count = std::count(text.begin(), text.end(), newline);
if(count > 0)
rowheight[i] = count * 20;
else
rowheight[i] = 20;
totrowheight += rowheight[i];
text = "";
}
table1.SetModel(tablemodel1);
double colwidth[2] = { 150, pPage->GetPageSize().GetWidth() - 150 - 40};
table1.SetColumnWidths(colwidth);
table1.SetRowHeights(rowheight);
table1.SetTableWidth(pPage->GetPageSize().GetWidth()-40);
table1.SetTableHeight(pPage->GetPageSize().GetHeight()-60);
table1.Draw(20, pPage->GetPageSize().GetHeight()- 40, &painter);
painter.FinishPage();
document->Close();
Sorry for my bad english and thanks a lot in advance
table1.SetAutoPageBreak(true,
[](PoDoFo::PdfRect &rect, void* pCustom)->PoDoFo::PdfPage*{
PoDoFo::PdfPage *pPage = ((PoDoFo::PdfStreamedDocument*)pCustom)->CreatePage(PoDoFo::PdfPage::CreateStandardPageSize(PoDoFo::ePdfPageSize_A4, true));
return pPage;
}, (void*) document);
I solved, was more easy than expected.
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();
}
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.
I'm trying to write a json structure using rapidjson the sax way. Here's what I do:
StringBuffer sb;
PrettyWriter<StringBuffer> writer(sb);
writer.StartObject();
writer.Key("user");
writer.StartArray();
OperatorAcPtrList::iterator xIt;
for (xIt = userList.begin(); xIt != userList.end(); xIt++)
{
writer.Key("userId");
writer.Uint((*xIt)->id);
writer.Key("productIdList");
writer.StartArray();
ProductIdList::iterator xPrdIdIt;
for (xPrdIdIt = ((*xIt)->productList).begin();
xPrdIdIt != ((*xIt)->productList).end(); xPrdIdIt++)
{
writer.Uint(*xPrdIdIt);
}
writer.EndArray();
}
writer.EndArray();
writer.EndObject();
But the result is not what I'd expect, it's:
{
"userList": [
"userId",
20,
"productIdList",
[
1,
2
],
"userId",
21,
"productIdList",
[
1,
2
]
]
}
It looks like everything inside the first StartArray EndArray becomes an array element. What I'd like to obtain instead is:
{
"userList": [
{
"userId" : 20,
"productIdList" : [1, 2],
},
{
"userId" : 21,
"productIdList" : [1, 2]
}
]
}
Am I doing something wrong or what I want is not supported at all?
Before you call writer.Key("userId"); in the for loop, add writer.StartObject();, and add writer.EndObject(); correspondingly. Here is an example:
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include <iostream>
using namespace rapidjson;
using namespace std;
int main() {
StringBuffer s;
Writer<StringBuffer> writer(s);
writer.StartObject();
writer.Key("userList");
writer.StartArray();
writer.StartObject();
writer.Key("userId");
writer.Uint(20);
writer.Key("productIdList");
writer.StartArray();
for (unsigned i = 1; i < 3; i++)
writer.Uint(i);
writer.EndArray();
writer.EndObject();
writer.StartObject();
writer.Key("userId");
writer.Uint(21);
writer.Key("productIdList");
writer.StartArray();
for (unsigned i = 1; i < 3; i++)
writer.Uint(i);
writer.EndArray();
writer.EndObject();
writer.EndArray();
writer.EndObject();
cout << s.GetString() << endl;
}