Ingo Mi
Ingo Mi

Reputation: 1069

Minimal Example on how to read, write and print QJson code (with QJsonDocument, QJsonArray, QJsonObject, QFile)

I am searching for a minimal full executable qt or c++ code example to parse and write this Json code:

{
    "FirstName": "John",
    "LastName": "Doe",
    "MiddleName": null,
    "Age": 43,

    "Address": {
        "Street": "Downing Street 10",
        "City": "London",
        "Country": "Great Britain"
    },
    "Phone numbers": [
        "+44 1234567",
        "+44 2345678"
    ]
    "Valid":true,
}

EDIT:

And yes, I have seen a "Save Game Example" and tried to figure it out.

But after nearly a week I gave up to transfer a minimal Example without enums, QVectors and 3 different header Files over to my project to handle the code snippet. Doesn't matter if its for a widget or core code.

I already did a xml read and write program successfully but it seems I miss some Important point and get errors with json that may or may not have to do with the parsing. I am not able to rule it out without a minimal fully working code example.

So my question is: Could you please provide a minimal Example to write, read and print the Json file? Thanks upfront.

Upvotes: 4

Views: 15274

Answers (2)

Ingo Mi
Ingo Mi

Reputation: 1069

I guess it might help someone else too, I figured it all out, thanks to @Botje for his example, really helped. In general it is easy for me to remember to represent data as QByteArray in the memory.

A minimal example to access and also use every single value stored in a json file, you are welcome:

(Yes, I could have written it even more compact but I guess this makes it easier to understand, so I spared functions/classes/structs for the sake of readability.)

#include <QCoreApplication>
#include <QString>
#include <QVariant>
#include <QFile>
#include <QByteArray>
#include <QTextStream>
#include <QDebug>

//json specific
#include <QJsonParseError>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonParseError>
#include <QJsonValue>


    void writeJsonFile();
    void readJsonFile();


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    writeJsonFile();
    readJsonFile();

    return a.exec();
}

void writeJsonFile()
{
    qDebug() << "Write Json File: ";

    //1. Create a QJsonObject and add values to it
    QJsonObject jsonObj;
    jsonObj["FirstName"] = "John";
    //no value will be written as null in the json file
    jsonObj["MiddleName"];
    jsonObj["LastName"] = "Doe";
    jsonObj["Age"] = 43;

    //2. Create Item of Json Object content (object of object)
    QJsonObject jsonItemObj;
    jsonItemObj["Street"] = "Downing Street 10";
    jsonItemObj["City"] = "London";
    jsonItemObj["Country"] = "Great Britain";
    //3. Add jsonItemObj to jsonObj and give it an object Name
    jsonObj["Address"] = jsonItemObj;

    //4. Create jsonArray and fill it with values - similar to filling a vector
    QJsonArray jsonArray;
    jsonArray.append("+44 1234567");
    jsonArray.append("+44 2345678");

    //Add a bool to the Object
    jsonObj["Valid"] = true;

    //5. Add jsonArray to jsonObj and give it an object Name
    jsonObj["Phone numbers"] = jsonArray;
    //(It can also be added to the jsonItemObj to be inline with the Address section)
    //with jsonItemObj["Phone numbers"] = jsonArray or as much objects of objects
    //you need


    /* As I understood it, most Qt classes use a QByteArray to handle data internally
     * because it is really fast/efficient,
     * also QFile QIODevice, it is a good idea to hold the read/write
     * QIODevice data as QByteArray in the Memory
     */

    //6. Create a QByteArray and fill it with QJsonDocument (json formatted)
    QByteArray byteArray;
    byteArray = QJsonDocument(jsonObj).toJson();

    //7. Open a QFile and write the byteArray filled with json formatted data
    //thanks to the QJsonDocument() Class to the file
    QFile file;
    file.setFileName("file.json");
    if(!file.open(QIODevice::WriteOnly)){
        qDebug() << "No write access for json file";
        return;
    }

    //8. finally write the file and close it
    file.write(byteArray);
    file.close();

    //9. Print out the byteArray to the terminal
    QTextStream textStream(stdout);
    textStream << "Rendered json byteArray text: " << endl;
    textStream << byteArray << endl;
}

void readJsonFile()
{
    qDebug() << "Read Json File:";

    //1. Open the QFile and write it to a byteArray and close the file
    QFile file;
    file.setFileName("file.json");
    if(!file.open(QIODevice::ReadOnly)){
        qDebug() << "Json filef couldn't be opened/found";
        return;
    }

    QByteArray byteArray;
    byteArray = file.readAll();
    file.close();

    //2. Format the content of the byteArray as QJsonDocument
    //and check on parse Errors
    QJsonParseError parseError;
    QJsonDocument jsonDoc;
    jsonDoc = QJsonDocument::fromJson(byteArray, &parseError);
    if(parseError.error != QJsonParseError::NoError){
        qWarning() << "Parse error at " << parseError.offset << ":" << parseError.errorString();
        return;
    }

    //3. Create a jsonObject and fill it with the byteArray content, formatted
    //and holding by the jsonDocument Class
    QJsonObject jsonObj;
    jsonObj = jsonDoc.object();

    //4. Now picking the jsonValues and printing them out or do what ever you need
    QJsonValue jsonVal;
    QTextStream textStream(stdout);

    jsonVal = jsonObj.value("FirstName");
    textStream << jsonVal.toString() << endl;

    jsonVal = jsonObj.value("MiddleName");
    //null gets back to an empty fild - added the sting "null/empty" to make it visible
    textStream << jsonVal.toVariant().toString() << "null/empty" << endl;

    jsonVal = jsonObj.value("LastName");
    textStream << jsonVal.toString() << endl;

    //The number has to be converted to an int and than to a string to print it
    jsonVal = jsonObj.value("Age");
    textStream << QString::number(jsonVal.toInt()) << endl;

    //5. Now we need to fill the object of the object. To do that, we need
    //the Item Object and a jsonSubVal object for json without a loop
    QJsonObject jsonItemObj;
    QJsonValue jsonSubVal;

    jsonVal = jsonObj.value(QString("Address"));
    jsonItemObj = jsonVal.toObject();

       jsonSubVal = jsonItemObj["Street"];
       textStream << jsonSubVal.toString() << endl;

       jsonSubVal = jsonItemObj["City"];
       textStream << jsonSubVal.toString() << endl;

       jsonSubVal = jsonItemObj["Country"];
       textStream << jsonSubVal.toString() << endl;

    //6. now the Phone Numbers array with a loop
    QJsonArray jsonArray;
    jsonArray = jsonObj["Phone numbers"].toArray();

    for(int i = 0; i < jsonArray.size(); i++)
        textStream << jsonArray[i].toString() << endl;

    textStream << "or with foreach" << endl;

    foreach(QJsonValue v, jsonArray)
        textStream << v.toString() << endl;

    //7. And finally the bool value:
    jsonVal = jsonObj.value(QString("Valid"));
    textStream << jsonVal.toVariant().toString() << endl;

    textStream << "or as number, not a string: ";

    textStream << (QString::number(jsonVal.toInt())) << endl;

    textStream << "\nThe whole file as printed in the file \n" <<
                  jsonDoc.toJson(QJsonDocument::Indented);



enter image description here

Upvotes: 6

Botje
Botje

Reputation: 30830

Since there does not seem to be a clear example on SO I wrote one. It uses simple mutation to create the objects, but if you have access to C++11 you should take a look at the std::initializer_list constructors, they make construction of objects much more compact.

#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
#include <QtGlobal>
#include <QTextStream>
#include <QDebug>
int main() {
    // 1. Create the document
    QJsonObject root;
    root["FirstName"] = "John";
    root["LastName"] = "Doe";
    root["Age"] = 43;

    // Construct nested object first, then store it in `root`
    QJsonObject Address;
    Address["Street"] =  "Downing Street 10";
    Address["City"] =  "London";
    Address["Country"] =  "Great Britain";
    root["Address"] = Address;

    QJsonArray PhoneNumbers;
    PhoneNumbers.push_back("+44 1234567");
    PhoneNumbers.push_back("+44 2345678");
    root["Phone Numbers"] = PhoneNumbers;

    // `ba` contains JSON
    QByteArray ba = QJsonDocument(root).toJson();
    QTextStream ts(stdout);
    ts << "rendered JSON" << endl;
    ts << ba;
    {
        QFile fout("test.json");
        fout.open(QIODevice::WriteOnly);
        fout.write(ba);
    }

    // 2. Now read it back in
    QJsonParseError parseError;
    QJsonDocument doc2;
    {
        QFile fin("test.json");
        fin.open(QIODevice::ReadOnly);
        QByteArray ba2 = fin.readAll();
        doc2 = QJsonDocument::fromJson(ba2, &parseError);
    }

    if (parseError.error != QJsonParseError::NoError) {
        qWarning() << "Parse error at" << parseError.offset << ":" << parseError.errorString();
    } else {
        ts << "parsed JSON" << endl;
        ts << doc2.toJson(QJsonDocument::Compact); 
                     //or QJsonDocument::Indented for a JsonFormat
    }
}

Upvotes: 14

Related Questions