Here is an example of JSON:
{
"sets": [
{
"id": "123",
"start": "Alpha",
"end": "Theta",
"units": [
{
"id": " A",
"name": "nameA",
"position": 1,
"capacity": 7
},
{
"id": "nameB",
"name": "WWW4561",
"position": 2,
"capacity": 15
}
]
},
{
"id": "456",
"start": "Beta",
"end": "Zeta",
"units": [
{
"id": "B",
"name": "nameB",
"position": 1,
"capacity": 9
},
{
"id": "F",
"name": "nameF",
"position": 1,
"capacity": 18
}
]
}
]
}
I want to store the parsed data in a container such that I will be able to access any unit item from units
given the start
and end
values of the sets
. If I am not mistaken this should be done using a dictionary
.
Currently, I can only iterate through the sets
and the units
only. Here is what I tried:
QNetworkReply *json_reply;
QJsonObject jsonObject= QJsonDocument::fromJson(json_reply->readAll()).object();
QJsonArray sets_array = jsonObject["sets"].toArray();
QJsonArray units_array = jsonObject[""].toArray(); // explicitly empty array
int idx = 0;
for (const QJsonValue& set_val: sets_array)
{
QJsonObject set_loopObj = set_val.toObject();
qDebug() << "\nset" << idx;
qDebug() << " id:" << set_loopObj["id"].toString();
qDebug() << "start:" << set_loopObj["start"].toString();
qDebug() << "end:" << set_loopObj["end"].toString();
units_array.append(set_loopObj["units"].toArray());
int idy = 0;
for (const QJsonValue& unit_val: units_array)
{
QJsonObject unit_loopObj = unit_val.toObject();
qDebug() << "\nunit";
qDebug() << "id:" << unit_loopObj["id"].toString();
qDebug() << "name:" << unit_loopObj["name"].toString();
qDebug() << "position:" << unit_loopObj["position"].toDouble();
qDebug() << "capacity:" << unit_loopObj["capacity"].toDouble();
++idy;
}
++idx;
}
qDebug() << "\nsets_array" << sets_array;
qDebug() << "\nunits_array" << units_array;
UPDATE
For example, I expect that by giving "Alpha","Theta"
to get both units of the first set as an array so that I should be able to access individual units by giving an indice (eg 1 for the 2nd unit).
I would also want to get the rest of the sets info ( id
) as well when providing the "Alpha, Theta"
keys.
Please provide code in your answers cause I am newbie.
I'd definitely break this into two tasks. The first subtask to to actually grab the appropriate object by its start and end.
QJsonObject find_by_start_and_end(const QJsonObject& obj,
const QString& start,
const QString& end) {
QJsonArray sets_array = jsonObject["sets"].toArray();
// For every object in the array, check if its start and end are the target.
// If so return it.
for(const auto& set_obj: sets_array) {
QJsonObject set = set_obj.toObject();
if(set["start"].toString() == start && set["end"].toString() == end) {
return set;
}
}
// If there are no matches, return an empty object.
return QJsonObject{};
}
Now you can search by (start, end) tuple--what a great feeling. By grabbing this entire object, you have all the information about it: the start, the end, the id, and all the units.
Now you just need to create a function that uses this helper to index into the units array appropriately.
QJsonObject get_kth_unit_by_start_and_end(const QJsonObject& obj,
const QString& start,
const QString& end,
const std::size_t k) {
// get the target by start and end tuple
const QJsonObject target_obj = find_by_start_and_end(obj, start, end);
// If the target is empty, the `units` array will not exist.
if(target_obj.empty())
return target_obj;
// get the units array from that returned target
QJsonArray units = target_obj["units"].toArray();
if(units.size() <= k) {
throw std::runtime_exception("Invalid k.");
}
// return the kth unit object.
return units[k].toObject();
}
I haven't tested this; however, this should give you a good start.
units_array.append(set_loopObj["units"].toArray());
int idy = 0;
for (const QJsonValue& unit_val: units_array)
{
QJsonObject unit_loopObj = unit_val.toObject();
When using append
on units_array
, you add the whole value passed as argument as a single element at the end of the array. Your for-loop is then filling unit_val
with the current element, so the whole array, which you try to read as an object.
I think what you wanted to achieve is:
units_array = set_loopObj["units"].toArray();
int idy = 0;
for (const QJsonValue& unit_val: units_array)
{
QJsonObject unit_loopObj = unit_val.toObject();
Here you can just remove units_array
and write:
int idy = 0;
for (const QJsonValue& unit_val: set_loopObj["units"].toArray())
{
QJsonObject unit_loopObj = unit_val.toObject();
You can do the same for sets_array
and write:
int idx = 0;
for (const QJsonValue& set_val: jsonObject["sets"].toArray())
{
QJsonObject set_loopObj = set_val.toObject();
About storing the data, first declare structures to represent your data:
struct MyUnit
{
QString id;
QString name;
int position;
int capacity;
};
struct MySet
{
QString id;
QString start;
QString end;
QVector<MyUnit> units;
};
You can then use something like that:
QMap<QPair<QString, QString>, MySet> data;
for (const QJsonValue& set_val: jsonObject["sets"].toArray())
{
QJsonObject set_loopObj = set_val.toObject();
// parse id, start, and end
QVector<MyUnit> units;
for (const QJsonValue& unit_val: set_loopObj["units"].toArray())
{
QJsonObject unit_loopObj = unit_val.toObject();
// parse id, name, position, and capacity
units.append(MyUnit{id, name, position, capacity});
}
data.insert(qMakePair(start, end), MySet{id, start, end, units});
}
And use it:
MySet at_set = data.value(qMakePair("Alpha", "Theta"));
qDebug() << at_set.id;
for(MyUnit at_unit: at_set.units)
{
// use at_unit
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.