Reading a QJsonDocument without additional copies

85 views Asked by At

I'm trying to read a QJsonDocument, and I want to minimize the number of copies made. When I read example code by others, it looks like they are making two or three copies of the data just to read it. Part of the problem is that I don't know what's a copy of the document and what's essentially a pointer to the document.

The documentation hasn't been much help. Here's how I've imagined it my head, but I don't think this is accurate:

  • QJsonDocument is like a top level QJsonObject that provides document-level member functions. It stores the entire document.
  • QJsonObject is an ordered tree-like object where nodes correspond to keys. I think a QJsonObject keeps a copy of the section of the document it points to, even though that would be inefficient.
  • QJsonValueRef is like a reference to a QJsonObject, although I can't tell why iterators aren't used instead of QJsonValueRef. It also seems difficult to use QJsonValueRef without copying the contents of the QJsonObject.

Suppose we want to read "Street", "City", and "County" from this json:

{
    "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,
}

This stackoverflow answer provides a solution below. I have numbered some lines for my question.

QJsonObject jsonObj = jsonDoc.object(); // (1)
QTextStream textStream(stdout);

QJsonValue jsonVal = jsonObj.value(QString("Address")); // (2)
QJsonObject jsonItemObj = jsonVal.toObject(); // (3)

QJsonValue jsonSubVal;

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

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

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

Out of (1)-(5), which are copies? Is there a way to eliminate these copies? (In line (5), I am referring to jsonSubVal.toString() rather than textStream <<.)

1

There are 1 answers

5
Alan Birtles On

value() returns by value so will always be a copy.

operator[] returns a reference when used on a non-const object but by value when called on a const object. Note that the non-const version will modify the object if the requested key doesn't exist. Also note that by assigning the result of the operator to QJsonValue you are forcing it to copy, use QJsonValueRef instead.

To avoid copies you can use find which returns iterators.

Not however that once you have a QJsonValueRef there doesn't seem to be a way to get to the contained object without making a copy see How to change QJsonObject value in a QJson hierarchy without using copies?

You might want to find a better JSON library if avoiding copying is important to you.