通过Qt C ++中的键访问解析嵌套JSON

时间:2016-10-06 10:27:10

标签: c++ json c++11 dictionary qt5

以下是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
    }
    ]
   }
  ]
}

我希望将已解析的数据存储在容器中,以便在unitsstart end值的情况下,我可以访问sets中的任何单位项}。如果我没有弄错,应该使用dictionary

目前,我只能遍历setsunits。 这是我试过的:

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;

更新

例如,我希望通过给"Alpha","Theta"将第一组的两个单位作为一个数组来使我能够通过给出一个指数来访问各个单位(例如,对于第二个单位来说是1)。

我还希望在提供id密钥时获取其余的集信息("Alpha, Theta")。

请在答案中提供代码,因为我是新手。

2 个答案:

答案 0 :(得分:2)

我绝对会把它分成两个任务。第一个子任务是通过它的开始和结束来实际获取适当的对象。

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{};
}

现在你可以搜索(开始,结束)元组 - 这是多么美好的感觉。通过抓取整个对象,您可以获得有关它的所有信息:开始,结束,ID和所有单位。

现在你只需要创建一个使用这个帮助器来适当地索引单元数组的函数。

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();
}

我没有测试过这个;但是,这应该会给你一个良好的开端。

答案 1 :(得分:1)

units_array.append(set_loopObj["units"].toArray());

int idy = 0;
for (const QJsonValue& unit_val: units_array)
{
    QJsonObject unit_loopObj = unit_val.toObject();

append上使用units_array时,将作为参数传递的整个值添加为数组末尾的单个元素。你的for循环然后用当前元素填充unit_val,所以整个数组,你尝试读取它作为对象。

我认为你想要达到的目标是:

units_array = set_loopObj["units"].toArray();

int idy = 0;
for (const QJsonValue& unit_val: units_array)
{
    QJsonObject unit_loopObj = unit_val.toObject();

您可以在这里删除units_array并写下:

int idy = 0;
for (const QJsonValue& unit_val: set_loopObj["units"].toArray())
{
    QJsonObject unit_loopObj = unit_val.toObject();

您可以对sets_array执行相同操作并编写:

int idx = 0;
for (const QJsonValue& set_val: jsonObject["sets"].toArray())
{
    QJsonObject set_loopObj = set_val.toObject();

关于存储数据,首先声明表示数据的结构:

struct MyUnit
{
    QString id;
    QString name;
    int position;
    int capacity;
};

struct MySet
{
    QString id;
    QString start;
    QString end;
    QVector<MyUnit> units;
};

然后你可以使用类似的东西:

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});
}

并使用它:

MySet at_set = data.value(qMakePair("Alpha", "Theta"));

qDebug() << at_set.id;

for(MyUnit at_unit: at_set.units)
{
    // use at_unit
}