How do I create JSON array using QT - c++

I want store my datas in JSON file like:
{
"plottingData": [
{
"min": 17,
"max": 35,
"mean": 20
},
{
"min": 7,
"max": 35,
"mean": 17
},
{
"min": 8,
"max": 50,
"mean": 29
}
]
}
How can I create this struct?
I used to QJsonObject but I couldn't add QJsonArray like this.

From Qt documentation:
QJsonArray plot_array;
// use initializer list to construct QJsonObject
auto data1 = QJsonObject(
{
qMakePair(QString("min"), QJsonValue(17)),
qMakePair(QString("max"), QJsonValue(35)),
qMakePair(QString("mean"), QJsonValue(20))
});
plot_array.push_back(QJsonValue(data1));
// Or use insert method to create your QJsonObject
QString min_str("min");
QString max_str("max");
QString mean_str("mean");
for(auto item : your_collection)
{
QJsonObject item_data;
item_data.insert(min_str, QJsonValue(item.min));
item_data.insert(max_str, QJsonValue(item.max));
item_data.insert(mean_str, QJsonValue(item.mean));
plot_array.push_back(QJsonValue(item_data));
}
QJsonObject final_object;
final_object.insert(QString("plottingData"), QJsonValue(plot_array));

QJsonObject o1
{
{ "min", 17 },
{ "max", 35 },
{ "mean", 20 },
};
QJsonObject o2;
o2 [ "min" ] = 7;
o2 [ "max" ] = 35;
o2 [ "mean"] = 17;
QJsonArray arr;
arr.append ( o1 );
arr.append ( o2 );
QJsonObject obj;
obj [ "plottingData" ] = arr;
//to see the JSON output
QJsonDocument doc ( obj );
qDebug() << doc.toJson ( QJsonDocument::Compact ); // or QJsonDocument::Indented
// output: "{\"plottingData\":[{\"max\":35,\"mean\":20,\"min\":17},{\"max\":35,\"mean\":17,\"min\":7}]}"

Related

Qt C++ Parsing JSON nested data from API response using JsonDocument

I have the following JSON response read from an API, using QJsonDocument, and I'm trying to read the postal codes value:
{
"data": {
"website": "https://somesite.com/",
"name": "SomeSite",
"description": "description of the product",
"techs": [
"sitetech1",
"sitetech2"
],
"state": null,
"city": null,
"postal codes": [
{
"value": "123456",
}
]
}
}
With the following code I read the response:
QStringList postals;
QString jsonText = (QString)reply->readAll();
QJsonDocument jsonResponse = QJsonDocument::fromJson(jsonText.toUtf8());
QJsonObject jsonObject = jsonResponse.object();
QJsonArray jsonArray = jsonObject["data"].toArray();
if(jsonArray.isEmpty()) {
qDebug() << "jsonArray is empty"; // this gets to here.
return "empty";
}
foreach (const QJsonValue & value, jsonArray) {
QJsonObject obj = value.toObject();
QJsonArray arr = obj["postal codes"].toArray();
foreach(const QJsonValue & value, arr) {
postals.append(obj["value"].toString());
}
}
}
But it seems like the jsonArray is empty. Did I parse the JSON incorrectly?
"data" does not seem to be an array, so "toArray()" fails. Also, in the loop, you are looking for the key "value" inside the wrong object it seems. Also, there is a comma which shouldn't be there in the json.
Something like this maybe?
{
"data": [
{
"website": "https://somesite.com/",
"name": "SomeSite",
"description": "description of the product",
"techs": [
"sitetech1",
"sitetech2"
],
"state": null,
"city": null,
"postal codes": [
{
"value": "123456"
}
]
}
]
}
code:
QString jsonText = f.readAll();
QJsonParseError error;
QJsonDocument jsonResponse = QJsonDocument::fromJson(jsonText.toUtf8(), &error);
if (error.error != QJsonParseError::NoError)
qDebug() << "Error:" << error.errorString();
QJsonObject jsonObject = jsonResponse.object();
QJsonArray jsonArray = jsonObject["data"].toArray();
if (jsonArray.isEmpty()) {
qDebug() << "jsonArray is empty"; // this gets to here.
return -1;
}
for (const QJsonValue & value : jsonArray) {
QJsonObject obj = value.toObject();
QJsonArray arr = obj["postal codes"].toArray();
for (const QJsonValue & value : arr) {
postals.append(value["value"].toString());
qDebug() << "val:" << value["value"].toString();
}
}
output:
val: "123456"

How to read such a nested json array in Qt?

Im trying to read json file with qt c++. After reading i will do some operations. I've read my json like it, but i want to print spesific datas, which include "float".
After finding them, i will assign a value each of these.
Thanks for any help
{
"A":[
{
"GPS":[
{
"GPS ID":[
"integer",
"0"
],
"GPS Mod":[
"integer",
"1"
],
"GPS Utc":[
"float",
"2"
],
"GPS Latitude":[
"float",
"3"
],
"GPS Longitude":[
"float",
"4"
]
}
]
Here is what I have tried up to now:
QByteArray data = file.readAll();
QJsonDocument doc = QJsonDocument::fromJson(data);
QJsonObject root = doc.object();
QJsonArray tlmtArray = root.value("A").toArray();
for(int i=0; i<tlmtArray.size(); i++)
{
QJsonObject obj = tlmtArray.at(i).toObject();
}
Actually, you seem to already know what you need to do to handle Json data, you just have to continue to unpack your nested structures until the leaf data.
I'm not sure what was your issue, you just had to continue what you were doing but anyway, I have written an example that prints in the console the inner GPS data of the following structure (the one that you provided, I just added the missing braces and brackets):
{
"A":
[
{
"GPS":
[
{
"GPS ID":[
"integer",
"0"
],
"GPS Mod":[
"integer",
"1"
],
"GPS Utc":[
"float",
"2"
],
"GPS Latitude":[
"float",
"3"
],
"GPS Longitude":[
"float",
"4"
]
}
]
}
]
}
Here is the example function:
int printJsonData(const QByteArray & json_data)
{
QJsonParseError err;
QJsonDocument doc = QJsonDocument::fromJson(json_data, &err);
if(err.error != QJsonParseError::NoError)
return -1; // Failure
QJsonObject root = doc.object();
QJsonArray tlmtArray = root.value("A").toArray();
for(int i = 0; i < tlmtArray.size(); ++i)
{
QJsonObject obj = tlmtArray[i].toObject();
QJsonArray gps_array = obj.value("GPS").toArray();
for(int j = 0; j < gps_array.size(); ++j)
{
QJsonObject gps_obj = gps_array[j].toObject();
for(QJsonObject::const_iterator cit = gps_obj.constBegin(); cit != gps_obj.constEnd(); ++cit)
{
std::cout << cit.key().toStdString() << ": (";
QJsonArray inner_data = cit.value().toArray();
for(int k = 0; k < inner_data.size(); ++k)
{
std::cout << inner_data[k].toString().toStdString() << (k < inner_data.size()-1 ? "," : "");
}
std::cout << ")\n";
}
}
}
return 0;
}
Output:
GPS ID: (integer,0)
GPS Latitude: (float,3)
GPS Longitude: (float,4)
GPS Mod: (integer,1)
GPS Utc: (float,2)
Please note that you really should use the methods QJsonObject::contains(), QJsonValue::isArray(), QJsonValue::isObject() and QJsonValue::isString() that Qt provides in order to check that the data you are extracting are exactly what you expect them to be. I didn't write such checks in the example because it is just an example and I wanted to avoid clutter and make the code less readable.

How to delete nested json data using nlohmann c++

I have a below json data. I am using nlohmann json in C++.
{
"CompanyName": "XYZ Tech",
"Created": "2019-10-16T20:14:29Z",
"TxnId": "4509237",
"Tags": [
{
"ROIId": "Default",
"Time": 71,
"Tracker": "emp10"
},
{
"ROIId": "MC16",
"Time": 21,
"TrackerId": "emp10"
},
{
"ROIId": "Default",
"Time": 11,
"TrackerId": "emp11"
},
{
"ROIId": "MC18",
"Time": 10,
"TrackerId": "emp11"
}
],
"Type": "TxnData"
}
In above json data, inside Tags, we have data where the ROIId is Default. I want to delete it so that the data becomes:
{
"CompanyName": "XYZ Tech",
"Created": "2019-10-16T20:14:29Z",
"TxnId": "4509237",
"Tags": [
{
"ROIId": "MC16",
"Time": 21,
"TrackerId": "emp10"
},
{
"ROIId": "MC18",
"Time": 10,
"TrackerId": "emp11"
}
],
"Type": "TxnData"
}
How can I do it in c++. Thanks
I suggest iterating through the json::array stored in Tags and saving the Key of the matched elements. This way you can later validate the deletion and safely delete the elements.
Note that deleting is exactly like erasing with a STL vector - I prefer to delete from the end of the vector to avoid changing the keys while deleting multiple elements.
Here is a quick and dirty demo
And here is the code:
#include <iostream>
#include <vector>
#include "json3.6.1.hpp"
unsigned removeDefaultROIID(nlohmann::json& jsonObject, const std::string& value) {
std::vector<int> toremove;
//Loop through the `tags` json::array and create a vector of indexes to delete:
for (auto &it : jsonObject["Tags"].items()) {
//`.get<std::string>()` is the best way to make sure we are getting the value as std::string
if (it.value().at("ROIId").get<std::string>() == value)
toremove.push_back(stoi(it.key()));
}
//sort it before erase - we want to delete first biggest index:
std::sort(toremove.rbegin(), toremove.rend());
//delete using `.erase()` method:
for (int &it : toremove)
jsonObject["Tags"].erase(jsonObject["Tags"].begin() + it);
return toremove.size();
}
int main()
{
//Create the JSON object:
nlohmann::json jsonObject = R"({"CompanyName":"XYZ Tech","Created":"2019-10-16T20:14:29Z","TxnId":"4509237","Tags":[{"ROIId": "Default","Time": 71,"Tracker": "emp10"},{"ROIId":"MC16","Time": 21,"TrackerId": "emp10"},{"ROIId":"Default","Time":11,"TrackerId":"emp11"},{"ROIId":"MC18","Time": 10,"TrackerId":"emp11"}],"Type":"TxnData"})"_json;
std::cout << "JSON nested object value conditional erase:" << std::endl;
std::cout << "JSON object TAGS count - BEFORE deletion:" << jsonObject["Tags"].size() << std::endl;
//Call the method -> jlson is passed by ref
unsigned removed = removeDefaultROIID(jsonObject, "Default");
std::cout << "JSON object TAGS count - AFTER deletion:" << jsonObject["Tags"].size() << std::endl;
return 0;
}

QJsonObject partial path from variable

I have a json object that I load:
QJsonObject json = CommonToolkit::Types::LoadJson(config);
Here is a partial of the json file content:
{
"config": {
"macos": {
"screen": {
"main": {
"height": 0,
"left": 0,
"top": 0,
"width": 0
}
},
"windows: {
}
What I do is check what os i'm running in. Using the following variable to store that os:
QString osPath;
In my test osPath = "macos"
So I want to update the applications geometry
QJsonObject jparam{
{ "height", value.height() },
{ "left", value.left() },
{ "width", value.width() },
{ "top", value.top() }
};
My problem is when I try to set jon with jparam using osPath:
json["config"][osPath]["screen"]["main"] = jparam;
The error I'm getting is:
/Users/adviner/Projects/Notes/src/Notes/data/config.cpp:87: error: type 'QJsonValueRef' does not provide a subscript operator
json["config"][osPath]["screen"]["main"] = jparam;
~~~~~~~~~~~~~~^~~~~~~
Editing a Json in Qt is not a simple task, in this case when using json["config"] you get a QJsonValueRef, this class is a helper to get other types of elements like QJsonObject, QJsonArray, int, QString, etc. by what to get the next element must be used toObject() but this value is a copy, so if you modify it, the initial element will not be modified, you have to reassign it.
QJsonObject json = CommonToolkit::Types::LoadJson(config);
QString osPath = "macos";
QJsonObject jparam{
{ "height", value.height() },
{ "left", value.left() },
{ "width", value.width() },
{ "top", value.top() }
};
// get objects
QJsonObject config_obj = json["config"].toObject();
QJsonObject osPath_obj = config_obj[osPath].toObject();
QJsonObject screen_obj = osPath_obj["screen"].toObject();
// modify param
screen_obj["main"] = jparam;
// set objects
osPath_obj["screen"] = screen_obj;
config_obj[osPath] = osPath_obj;
json["config"] = config_obj;

Qt JsonObjects and initializer lists -- deeper than one level?

This is in the documentation:
http://doc.qt.io/qt-5/qjsonobject.html#QJsonObject-1
Which shows that I can do:
QJsonObject o
{
{"x", 1},
{"y", 2}
}
...and that works, however
QJsonObject o
{
{"x", { "value", 1 } },
{"y", { "value", 2 } }
}
Does not compile. What am I missing?
You have to specify the type (QJsonObject or QJsonArray) in front of the initializer list {}, the compiler is unable to guess which one you want.
QJsonObject o
{
{"x", QJsonObject { {"key", "value"} }}
};
You could also try this approach, using C++11 raw string literal:
const QByteArray object = R"(
{
"x": { "value": "1" },
"y": { "value": "2" }
}
)";
QJsonObject jsonObject = QJsonDocument::fromJson(object).object();
qDebug() << jsonObject;