1

I am interested in seeing how we can use Qt's QJsonDocument to parse all entries from a simple nested JSON (as I have just started studying this).

nested json example:

{
    "city": "London",
    "time": "16:42",
    "unit_data": 
        [
            {
                "unit_data_id": "ABC123",
                "unit_data_number": "21"
            },
            {
                "unit_data_id": "DEF456",
                "unit_data_number": "12"
            }
        ]
}

I can parse the non-nested parts of it like so:

QJsonObject jObj;
QString city = jObj["city"].toString();
QString time = jObj["time"].toString();
frogatto
  • 28,539
  • 11
  • 83
  • 129

3 Answers3

9

I am not sure what you are asking, but perhaps this might help:

QJsonDocument doc;
doc = QJsonDocument::fromJson("{                                              "
                              "     \"city\": \"London\",                      "
                              "     \"time\": \"16:42\",                       "
                              "     \"unit_data\":                             "
                              "         [                                      "
                              "             {                                  "
                              "                 \"unit_data_id\": \"ABC123\",  "
                              "                 \"unit_data_number\": \"21\"   "
                              "             },                                 "
                              "             {                                  "
                              "                 \"unit_data_id\": \"DEF456\",  "
                              "                 \"unit_data_number\": \"12\"   "
                              "             }                                  "
                              "         ]                                      "
                              " }");

// This part you have covered
QJsonObject jObj = doc.object();
qDebug() << "city" << jObj["city"].toString();
qDebug() << "time" << jObj["time"].toString();
// Since unit_data is an array, you need to get it as such
QJsonArray array = jObj["unit_data"].toArray();
// Then you can manually access the elements in the array
QJsonObject ar1 = array.at(0).toObject();
qDebug() << "" << ar1["unit_data_id"].toString();
// Or you can loop over the items in the array
int idx = 0;
for(const QJsonValue& val: array) {
    QJsonObject loopObj = val.toObject();
    qDebug() << "[" << idx << "] unit_data_id    : " << loopObj["unit_data_id"].toString();
    qDebug() << "[" << idx << "] unit_data_number: " << loopObj["unit_data_number"].toString();
    ++idx;
}

The output I get is:

city "London"
time "16:42"
"ABC123"
[ 0 ] unit_data_id    :  "ABC123"
[ 0 ] unit_data_number:  "21"
[ 1 ] unit_data_id    :  "DEF456"
[ 1 ] unit_data_number:  "12"
CJCombrink
  • 3,738
  • 1
  • 22
  • 38
  • Quick follow-up question: how can we chech / make sure that the `QJsonArray` `array.at(i)` will not go out of range i.e. for `i>=2` in the example above? –  Sep 29 '16 at 12:26
  • @nk-fford You can get the size of the QJsonArray using the [QJsonArray::count()](http://doc.qt.io/Qt-5/qjsonarray.html#count) function. The range based for shown in the answer should not be able to go out of range. – CJCombrink Sep 29 '16 at 14:43
2

In JSON notation, everything should be formatted in key-value. Keys are always strings, but values could be string literals ("example"), number literals , arrays ([]) and objects ({}).

QJsonDocument::fromJson(...).object() returns the root object of a given JSON string. Recall that objects are written by {} notation. This method gives you a QJsonObject. This JSON object has 3 keys ("city", "name" and "unit_data") which value of these keys are of type string literal, string literal and array respectively.

So if you want to access the data stored in that array you should do:

QJsonArray array = rootObj["unit_data"].toArray();

Note that arrays don't have keys, they have only values which could be of the three types mentioned above. In this case, the array holds 2 objects which can be treated as other JSON objects. So,

QJsonObject obj = array.at(0).toObject();

Now the obj object points to the following object:

{
    "unit_data_id": "ABC123",
    "unit_data_number": "21"
}

So, you should now be able to do what you want. :)

frogatto
  • 28,539
  • 11
  • 83
  • 129
1

It can happen that one of the elements inside your JSON has more elements inside. It can also happen that you don't know the characteristics of the file (or you want to have a general function).

Therefore you can use a function for any JSON:

void traversJson(QJsonObject json_obj){
    foreach(const QString& key, json_obj.keys()) {

        QJsonValue value = json_obj.value(key);
        if(!value.isObject() ){
          qDebug() << "Key = " << key << ", Value = " << value;
         }
        else{
             qDebug() << "Nested Key = " << key;
             traversJson(value.toObject());
        }

    }

};
Til
  • 5,150
  • 13
  • 26
  • 34
Ivan
  • 1,352
  • 2
  • 13
  • 31