adding to json file without deleting the content
-
aaargh im blinded....
what am i doing wrong here? im trying to add to my json file! currently it deletes what is in the json and then sets the new entry in :/bool DeviceData::devicedataupdated() { DeviceDataDebugger.LevelInfo("DEVICEDATA", "INIT", "Adding New Device", "!"); QFile file("devices.json"); if ( !file.open(QIODevice::ReadOnly | QIODevice::Text) ) { DeviceDataDebugger.LevelInfo("DEVICEDATA", "OPEN", "Failed to open and / or read the file", "!"); return false; } QJsonParseError *error = new QJsonParseError(); QJsonDocument inputJsonDoc = QJsonDocument::fromJson(file.readAll(), error); file.close(); QJsonObject newDevice; newDevice.insert("IPA", "newdevice"); newDevice.insert("Icon", "fa_bolt"); newDevice.insert("Name", "New Device"); newDevice.insert("Status", "online"); newDevice.insert("Type", "Strip"); newDevice.insert("UVLights", "false"); QJsonArray allEntriesList = inputJsonDoc.array(); allEntriesList.push_back(newDevice); QJsonObject outputJsonObject ; outputJsonObject["New Device"] = allEntriesList; QJsonDocument outputJsonDoc; outputJsonDoc.setObject(outputJsonObject); if ( !file.open(QIODevice::WriteOnly | QIODevice::Text) ) { DeviceDataDebugger.LevelInfo("DEVICEDATA", "OPEN", "Failed to open and / or write to the file", "!"); return false; } file.write(outputJsonDoc.toJson()); file.close(); return true; DeviceDataDebugger.LevelSuccess("DEVICEDATA", "SUCCESS", "Created new device", "!"); }
-
Ah, I overlooked something. You need to read the inputJsonDoc into inputJsonObject first.
ReplaceQJsonObject inputJsonObject;
with
QJsonObject inputJsonObject = inputJsonDoc.object();
Sorry about that.
@AxelVienna thank you so much for the help! :)
ANSWER
bool MainWindow::addNewDevice() { AddDeviceDebugger.LevelInfo("DEVICEDATA", "INIT", "Adding New Device", "!"); QFile file("devices.json"); if ( !file.open(QIODevice::ReadOnly | QIODevice::Text) ) { AddDeviceDebugger.LevelInfo("DEVICEDATA", "OPEN", "Failed to open and / or read the file", "!"); return false; } QJsonParseError *error = new QJsonParseError(); QJsonDocument inputJsonDoc = QJsonDocument::fromJson(file.readAll(), error); file.close(); QJsonObject newDevice; newDevice.insert("IPA", "newdevice"); newDevice.insert("Icon", "fa_bolt"); newDevice.insert("Name", "New Device"); newDevice.insert("Status", "online"); newDevice.insert("Type", "Strip"); newDevice.insert("UVLights", "false"); QJsonObject inputJsonObject = inputJsonDoc.object(); inputJsonObject["New Device"] = newDevice; QJsonDocument outputJsonDoc; outputJsonDoc.setObject(inputJsonObject); if ( !file.open(QIODevice::WriteOnly | QIODevice::Text ) ) { AddDeviceDebugger.LevelInfo("DEVICEDATA", "OPEN", "Failed to open and / or write to the file", "!"); return false; } file.write(outputJsonDoc.toJson()); file.close(); return true; AddDeviceDebugger.LevelSuccess("DEVICEDATA", "SUCCESS", "Created new device", "!"); }
-
how it looks currently
{ "Studio Lights": { "IPA": "studiolights", "Icon": "fa_bolt", "Name": "Studio Lights", "Status": "online", "Type": "Strip", "UVLights": "false" } }
how it should look after adding/appending
{ "Studio Lights": { "IPA": "studiolights", "Icon": "fa_bolt", "Name": "Studio Lights", "Status": "online", "Type": "Strip", "UVLights": "false" } "newdevice": { "IPA": "studiolights", "Icon": "fa_bolt", "Name": "New Device", "Status": "online", "Type": "Strip", "UVLights": "false" } }
-
Your JSON file contains an object, not an array.
The line...QJsonArray allEntriesList = inputJsonDoc.array();
...will therefore create an empty allEntriesList, which you then append to newDevice.
The consequence is that newDevice contains nothing but the new device. Change the code as follows to fix the misbehavior:(...) QJsonObject newDevice; newDevice.insert("IPA", "newdevice"); newDevice.insert("Icon", "fa_bolt"); newDevice.insert("Name", "New Device"); newDevice.insert("Status", "online"); newDevice.insert("Type", "Strip"); newDevice.insert("UVLights", "false"); /* changes start here */ // QJsonArray allEntriesList = inputJsonDoc.array(); // allEntriesList.push_back(newDevice); // QJsonObject outputJsonObject ; // outputJsonObject["New Device"] = allEntriesList; inputJsonObject["New Device"] = newDevice; QJsonDocument outputJsonDoc; // outputJsonDoc.setObject(outputJsonObject); outputJsonDoc.setObject(inputJsonObject); /* no more changes from here */ if ( !file.open(QIODevice::WriteOnly | QIODevice::Text) ) { DeviceDataDebugger.LevelInfo("DEVICEDATA", "OPEN", "Failed to open and / or write to the file", "!"); return false; }
-
Your JSON file contains an object, not an array.
The line...QJsonArray allEntriesList = inputJsonDoc.array();
...will therefore create an empty allEntriesList, which you then append to newDevice.
The consequence is that newDevice contains nothing but the new device. Change the code as follows to fix the misbehavior:(...) QJsonObject newDevice; newDevice.insert("IPA", "newdevice"); newDevice.insert("Icon", "fa_bolt"); newDevice.insert("Name", "New Device"); newDevice.insert("Status", "online"); newDevice.insert("Type", "Strip"); newDevice.insert("UVLights", "false"); /* changes start here */ // QJsonArray allEntriesList = inputJsonDoc.array(); // allEntriesList.push_back(newDevice); // QJsonObject outputJsonObject ; // outputJsonObject["New Device"] = allEntriesList; inputJsonObject["New Device"] = newDevice; QJsonDocument outputJsonDoc; // outputJsonDoc.setObject(outputJsonObject); outputJsonDoc.setObject(inputJsonObject); /* no more changes from here */ if ( !file.open(QIODevice::WriteOnly | QIODevice::Text) ) { DeviceDataDebugger.LevelInfo("DEVICEDATA", "OPEN", "Failed to open and / or write to the file", "!"); return false; }
@AxelVienna so the new code looks like this
bool DeviceData::devicedataupdated() { DeviceDataDebugger.LevelInfo("DEVICEDATA", "INIT", "Adding New Device", "!"); QFile file("devices.json"); if ( !file.open(QIODevice::ReadOnly | QIODevice::Text) ) { DeviceDataDebugger.LevelInfo("DEVICEDATA", "OPEN", "Failed to open and / or read the file", "!"); return false; } QJsonParseError *error = new QJsonParseError(); QJsonDocument inputJsonDoc = QJsonDocument::fromJson(file.readAll(), error); file.close(); QJsonObject newDevice; newDevice.insert("IPA", "newdevice"); newDevice.insert("Icon", "fa_bolt"); newDevice.insert("Name", "New Device"); newDevice.insert("Status", "online"); newDevice.insert("Type", "Strip"); newDevice.insert("UVLights", "false"); QJsonObject inputJsonObject; inputJsonObject["New Device"] = newDevice; QJsonDocument outputJsonDoc; outputJsonDoc.setObject(inputJsonObject); if ( !file.open(QIODevice::WriteOnly | QIODevice::Text ) ) { DeviceDataDebugger.LevelInfo("DEVICEDATA", "OPEN", "Failed to open and / or write to the file", "!"); return false; } file.write(outputJsonDoc.toJson()); file.close(); return true; DeviceDataDebugger.LevelSuccess("DEVICEDATA", "SUCCESS", "Created new device", "!"); }
did i miss something? cause now "New Device" just replaces the "Studio Lights" entry!
-
Ah, I overlooked something. You need to read the inputJsonDoc into inputJsonObject first.
ReplaceQJsonObject inputJsonObject;
with
QJsonObject inputJsonObject = inputJsonDoc.object();
Sorry about that.
-
Ah, I overlooked something. You need to read the inputJsonDoc into inputJsonObject first.
ReplaceQJsonObject inputJsonObject;
with
QJsonObject inputJsonObject = inputJsonDoc.object();
Sorry about that.
@AxelVienna thank you so much for the help! :)
ANSWER
bool MainWindow::addNewDevice() { AddDeviceDebugger.LevelInfo("DEVICEDATA", "INIT", "Adding New Device", "!"); QFile file("devices.json"); if ( !file.open(QIODevice::ReadOnly | QIODevice::Text) ) { AddDeviceDebugger.LevelInfo("DEVICEDATA", "OPEN", "Failed to open and / or read the file", "!"); return false; } QJsonParseError *error = new QJsonParseError(); QJsonDocument inputJsonDoc = QJsonDocument::fromJson(file.readAll(), error); file.close(); QJsonObject newDevice; newDevice.insert("IPA", "newdevice"); newDevice.insert("Icon", "fa_bolt"); newDevice.insert("Name", "New Device"); newDevice.insert("Status", "online"); newDevice.insert("Type", "Strip"); newDevice.insert("UVLights", "false"); QJsonObject inputJsonObject = inputJsonDoc.object(); inputJsonObject["New Device"] = newDevice; QJsonDocument outputJsonDoc; outputJsonDoc.setObject(inputJsonObject); if ( !file.open(QIODevice::WriteOnly | QIODevice::Text ) ) { AddDeviceDebugger.LevelInfo("DEVICEDATA", "OPEN", "Failed to open and / or write to the file", "!"); return false; } file.write(outputJsonDoc.toJson()); file.close(); return true; AddDeviceDebugger.LevelSuccess("DEVICEDATA", "SUCCESS", "Created new device", "!"); }
-
Ah, I overlooked something. You need to read the inputJsonDoc into inputJsonObject first.
ReplaceQJsonObject inputJsonObject;
with
QJsonObject inputJsonObject = inputJsonDoc.object();
Sorry about that.
currently working code
bool MainWindow::addNewDevice() { AddDeviceDebugger.LevelInfo("DEVICEDATA", "INIT", "Adding New Device", "!"); QFile file("devices.json"); if ( !file.open(QIODevice::ReadOnly | QIODevice::Text) ) { AddDeviceDebugger.LevelInfo("DEVICEDATA", "OPEN", "Failed to open and / or read the file", "!"); return false; } QJsonParseError *error = new QJsonParseError(); QJsonDocument inputJsonDoc = QJsonDocument::fromJson(file.readAll(), error); file.close(); QJsonObject newDevice; newDevice.insert("IPA", "newdevice"); newDevice.insert("Icon", "fa_bolt"); newDevice.insert("Name", "New Device"); newDevice.insert("Status", "online"); newDevice.insert("Type", "Strip"); newDevice.insert("UVLights", "false"); QJsonObject inputJsonObject = inputJsonDoc.object(); inputJsonObject["New Device"] = newDevice; QJsonDocument outputJsonDoc; outputJsonDoc.setObject(inputJsonObject); if ( !file.open(QIODevice::WriteOnly | QIODevice::Text ) ) { AddDeviceDebugger.LevelInfo("DEVICEDATA", "OPEN", "Failed to open and / or write to the file", "!"); return false; } file.write(outputJsonDoc.toJson()); file.close(); return true; AddDeviceDebugger.LevelSuccess("DEVICEDATA", "SUCCESS", "Created new device", "!"); }
Json befor adding new entry
{ "Studio Lights": { "IPA": "studiolights", "Icon": "fa_bolt", "Name": "Studio Lights", "Status": "online", "Type": "Strip", "UVLights": "false" } }
after adding new entry
{ "New Device": { "IPA": "newdevice", "Icon": "fa_bolt", "Name": "New Device", "Status": "online", "Type": "Strip", "UVLights": "false" }, "Studio Lights": { "IPA": "studiolights", "Icon": "fa_bolt", "Name": "Studio Lights", "Status": "online", "Type": "Strip", "UVLights": "false" } }
why does the new entry come ontop and not underneath
"Studio Lights"
this is annoying when i then update and populate my device list with buttons for each device (from json file) the newly added one will be inserted ontop of the devices already listed :/ -
currently working code
bool MainWindow::addNewDevice() { AddDeviceDebugger.LevelInfo("DEVICEDATA", "INIT", "Adding New Device", "!"); QFile file("devices.json"); if ( !file.open(QIODevice::ReadOnly | QIODevice::Text) ) { AddDeviceDebugger.LevelInfo("DEVICEDATA", "OPEN", "Failed to open and / or read the file", "!"); return false; } QJsonParseError *error = new QJsonParseError(); QJsonDocument inputJsonDoc = QJsonDocument::fromJson(file.readAll(), error); file.close(); QJsonObject newDevice; newDevice.insert("IPA", "newdevice"); newDevice.insert("Icon", "fa_bolt"); newDevice.insert("Name", "New Device"); newDevice.insert("Status", "online"); newDevice.insert("Type", "Strip"); newDevice.insert("UVLights", "false"); QJsonObject inputJsonObject = inputJsonDoc.object(); inputJsonObject["New Device"] = newDevice; QJsonDocument outputJsonDoc; outputJsonDoc.setObject(inputJsonObject); if ( !file.open(QIODevice::WriteOnly | QIODevice::Text ) ) { AddDeviceDebugger.LevelInfo("DEVICEDATA", "OPEN", "Failed to open and / or write to the file", "!"); return false; } file.write(outputJsonDoc.toJson()); file.close(); return true; AddDeviceDebugger.LevelSuccess("DEVICEDATA", "SUCCESS", "Created new device", "!"); }
Json befor adding new entry
{ "Studio Lights": { "IPA": "studiolights", "Icon": "fa_bolt", "Name": "Studio Lights", "Status": "online", "Type": "Strip", "UVLights": "false" } }
after adding new entry
{ "New Device": { "IPA": "newdevice", "Icon": "fa_bolt", "Name": "New Device", "Status": "online", "Type": "Strip", "UVLights": "false" }, "Studio Lights": { "IPA": "studiolights", "Icon": "fa_bolt", "Name": "Studio Lights", "Status": "online", "Type": "Strip", "UVLights": "false" } }
why does the new entry come ontop and not underneath
"Studio Lights"
this is annoying when i then update and populate my device list with buttons for each device (from json file) the newly added one will be inserted ontop of the devices already listed :/@Kris-Revi
JSON object attributes are unordered. You cannot force it to output them in any particular order.If you must know/maintain an order per your example, you would have to e.g. add a further attribute into each object to indicate its order, and use that during restore. Or store as an array/list, which I think do have & preserve order.
Tiny points about your code:
return true; AddDeviceDebugger.LevelSuccess("DEVICEDATA", "SUCCESS", "Created new device", "!");
Ought generate a compiler warning. Reverse the order of the lines.
QJsonParseError *error = new QJsonParseError(); QJsonDocument inputJsonDoc = QJsonDocument::fromJson(file.readAll(), error);
This leaks the
new
edQJsonParseError
. Eitherdelete
it, or simpler allocate on stack and pass address:QJsonParseError error; QJsonDocument inputJsonDoc = QJsonDocument::fromJson(file.readAll(), &error);
-
@Kris-Revi
JSON object attributes are unordered. You cannot force it to output them in any particular order.If you must know/maintain an order per your example, you would have to e.g. add a further attribute into each object to indicate its order, and use that during restore. Or store as an array/list, which I think do have & preserve order.
Tiny points about your code:
return true; AddDeviceDebugger.LevelSuccess("DEVICEDATA", "SUCCESS", "Created new device", "!");
Ought generate a compiler warning. Reverse the order of the lines.
QJsonParseError *error = new QJsonParseError(); QJsonDocument inputJsonDoc = QJsonDocument::fromJson(file.readAll(), error);
This leaks the
new
edQJsonParseError
. Eitherdelete
it, or simpler allocate on stack and pass address:QJsonParseError error; QJsonDocument inputJsonDoc = QJsonDocument::fromJson(file.readAll(), &error);
-
@JonB said in adding to json file without deleting the content:
add a further attribute into each object to indicate its order
like what and how does that work?
ty for the pointers, they are fixed now :)
@Kris-Revi said in adding to json file without deleting the content:
like what and how does that work?
All I meant was you'd have to make your saved JSON like, say,
{ "New Device": { "IPA": "newdevice", ..., "Order": 1 }, "Studio Lights": { "IPA": "studiolights", ..., "Order": 0 } }
So I made each element have an
Order
attribute, counting from 0 upward like an array for the order they were in when I saved. Which as shown above happens randomly to have come out not in that order when saved. Now it's your responsibility when reloading and recreating "populate my device list with buttons for each device" to look at theOrder
attribute on each one and use that to order your device list as you want it to be.The other way, if order is so important, is not to store as just an object with an arbitrary list of named attributes (
"New Device":
,"Studio Lights":
...) as you have done here, precisely because you cannot order those. Instead store as an array/list like:{ [ { "Name": "New Device", "IPA": "newdevice", ..., "Order": 1 }, { "Name": "Studio Lights", "IPA": "studiolights", ..., "Order": 0 } ] }
This is an array/list of objects, so it does have an order which is preserved on save/restore. Of course, that then takes you back to your original code as to how to locate an object element by
Name
, but that's the price you pay if ordering is important to you.