Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QJsonObject: Insert in a deep field



  • I would like to insert/append a QJsonObject inside a deep QJsonObject/Array field.
    Example:

    QJsonObject root;
    
    QJsonArray my_array;
    
    QJsonObject first;
    first.insert("first", 1);
    
    my_array.append(first);
    
    root.insert("my_array", my_array);
    

    Until here...all ok.

    Now, I would like to append a second QJsonObject inside the my_array field.
    Like:

    QJsonObject second;
    second.insert("second", 2);
    
    root["my_array"].append(second); // Not working!
    

    Why? How can I fix it?



  • @fem_dev Hi,

    The issue here is that the compiler cannot know you are accessing a QJSonArray. QJsonValueRef QJsonObject::operator[](QStringView key) returns a QJsonValue, and not a QJsonArray, you can access the array using QJsonValue::toArray() const but then it returns a const array so you cannot modify it "on the fly"

    If you have still access to your array instance:

    my_array.append(first);
    ...
    my_array.append(second);
    root.insert("my_array", my_array);
    

    But if you don't, you need to get the array, append your data, and then put it back in the QJsonObject.

    QJsonArray myArray = root["my_array"].toArray();
    myArray.append(second);
    root["my_array"] = myArray;
    


  • @fem_dev Hi,

    The issue here is that the compiler cannot know you are accessing a QJSonArray. QJsonValueRef QJsonObject::operator[](QStringView key) returns a QJsonValue, and not a QJsonArray, you can access the array using QJsonValue::toArray() const but then it returns a const array so you cannot modify it "on the fly"

    If you have still access to your array instance:

    my_array.append(first);
    ...
    my_array.append(second);
    root.insert("my_array", my_array);
    

    But if you don't, you need to get the array, append your data, and then put it back in the QJsonObject.

    QJsonArray myArray = root["my_array"].toArray();
    myArray.append(second);
    root["my_array"] = myArray;
    


  • @Gojir4 thank you!

    If I use this:

    QJsonArray myArray = root["my_array"].toArray(); // Object copying?
    myArray.append(second);
    root["my_array"] = myArray;
    

    Question1:
    It is copying the array? Or just the pointer value?
    Is there a way to avoid object copying?

    Question 2:
    Ok, I understood that I need the toArray() method.
    But now, why I can't do that?

     root["my_array"].toArray().append(second); // Not working too
    

  • Lifetime Qt Champion

    Hi
    try
    root["my_array"] = root["my_array"].toArray().append(second);

    I think
    root["my_array"].toArray() is a copy and not a reference/pointer so you are modifying a temp object and not the
    original one.



  • @mrjj I tried:

    root["my_array"] = root["my_array"].toArray().append(second);
    

    But I got this compilation time error:

    app.cpp:392:26: error: no viable overloaded '='
    qjsonvalue.h:181:20: note: candidate function not viable: cannot convert argument of incomplete type 'void' to 'const QJsonValue' for 1st argument
    qjsonvalue.h:182:20: note: candidate function not viable: cannot convert argument of incomplete type 'void' to 'const QJsonValueRef' for 1st argument
    

    Question:
    Is there another way to append() avoiding the object copying below? Using a pointer or a reference?

    QJsonArray myArray = root["my_array"].toArray(); // Object copying?
    myArray.append(second);
    root["my_array"] = myArray;
    

  • Lifetime Qt Champion

    @fem_dev said in QJsonObject: Insert in a deep field:

    QJsonValueRef

    Ok it complains about incomplete type
    so i wonder if it misses an include?

    Anyway, @Gojir4 showed the working way.



  • It seems like the JSON objects in Qt are designed to be assembled rather than modified:
    https://doc.qt.io/qt-5/qtcore-serialization-savegame-example.html

    Is there a word for this type of code design?


  • Lifetime Qt Champion

    @fcarney
    Well its a value-orientated design utilizing the implicit sharing Qt provides making the copying cheap.
    However, it does allow ref for some of the constructs via QJsonValueRef

    Im not sure it has a concrete name other than maybe
    Surprising :)


Log in to reply