[SOLVED]QJsonDocument, QJsonValue, QJsonObject: How To Change Value from File



  • Hello again! I would love some help. I have a file that contains some JSON values and the file acts as a persistent store when values get changed inside my program. I have my program reading the values in just fine but I'm running into a little trouble when I try to change the values.

    The QT Docs are a little lacking and even the sparse examples I've found don't really address my particular problem. What I want to do is this: When a value that I want to store is changed, I want to update that particular key in the json file without having to change the entire file (every other key value).

    I'm using QT Creator 5.2.1 in Windows 7.

    This is what I've tried:
    @
    QFile configFile("MyConfig.json");
    QString inputData;

    if(configFile.open(QIODevice::ReadWrite | QIODevice::Text))
    {
        inputData = configFile.readAll();
        QJsonDocument jsonDoc = QJsonDocument::fromJson(inputData.toUtf8());  // This gets the document
        QJsonObject jo = jsonDoc.object(); // This converts the document into an object
        QJsonValue value = jo.value(QString("myValue")); // Contains the value I want to update before writing
    
      value = 10;  //  some Variable Value that I want to push back to the file
    

    ...
    @

    When I try this, I get a compile error message "error C2248: 'QJsonValue::QJsonValue' : cannot access private member declared in class 'QJsonValue'".

    So my question is how do I change the value of this QJsonValue? And will changing this value still allow me to write the entire JSON document back to the file with the new value?

    Thanks!


  • Moderators

    Hi,

    What is your compiler version? Which line is your compiler complaining about?

    QJsonValue has a private constructor to prevent wrong implicit typecasting:
    @
    // Private
    QJSonValue::QJsonValue(const void *);
    @

    Perhaps your compiler is interpreting "10" as a pointer value, since QJsonValue doesn't take integers. Try assigning a double instead:
    [object Object] = 10.0;@

    [quote]And will changing this value still allow me to write the entire JSON document back to the file with the new value?[/quote]Yes. Simply write your updated QJsonValue back into your QJsonObject, convert that into a QJsonDocument, then write it to a file.

    (The following is head-to-keyboard. Hopefully it doesn't contain bugs, but it shows you the idea)
    @
    value = 10.0;
    jo["myValue"] = value;
    jsonDoc.setObject(jo);

    configFile.resize(0); // Erase old contents
    configFile.write(jsonDoc.toBinaryData());
    @



  • I just put 10 in the example. I've tried bool, string, double... nothing works. Im using 5.2.1. And did I mention that nothing seems to work and my compiler complains regardless of how i try to assign. there appears to be no way to update the on an already created QJsonValue object... Ive never seen an object that wont let you assign to it as a way of preventing you from assigning the wrong thing. That seems like sewing someones mouth shut to prevent them from eating poison. Just sayin.



  • But thank you for your response JKSH



  • Sorry, you asked my compiler: Microsoft Visual C++ 11(amd64) and my kit is Desktop Qt 5.2.1 MSVC2012 OpenGL 64 bit.

    Here's the full source, Ive tried all your recommendations and nothing works:
    @
    void MyConfig::configValueChangedHandler(QString name, bool updateVal){
    QFile configFile("MyConfig.json");
    QString inputData;

    if(configFile.open(QIODevice::ReadWrite | QIODevice::Text))
    {
        inputData = configFile.readAll();
        QJsonDocument jsonDoc = QJsonDocument::fromJson(inputData.toUtf8());
        QJsonObject jo = jsonDoc.object();
        QJsonValue value = jo.value(QString(name));
        //value = value.toBool(updateVal);
    

    // jo.value(QString(name)) = jo.value(name).toBool(updateVal);
    // value = jo.value(QString(name));
    // value = value.operator =(updateVal);
    //value = updateVal;

    // QJsonValue subobj = item[name];
    // subobj. = updateVal;

        //item[name] = updateVal;
        configFile.write(jsonDoc.toJson());
    
        configFile.close();
    }
    

    }
    @

    I've left all the attempts to assign a value back to value in place. Thanks for your help. Still doesnt seem to be a way to assign a value to QJsonValue, or QJsonObject

    EDIT: Enclosed code in '@' tags -- JKSH


  • Moderators

    Ah, I JUST uninstalled MSVC 2012 from my system yesterday!

    Anyway, I made minor modifications to your code to make a fully-standalone program...
    @
    #include <QFile>
    #include <QJsonDocument>
    #include <QJsonObject>

    int main(int argc, char *argv[])
    {
    QString name;
    bool updateVal;

    QFile configFile&#40;"MyConfig.json"&#41;;
    QString inputData;
    
    if(configFile.open(QIODevice::ReadWrite | QIODevice::Text))
    {
        inputData = configFile.readAll();
        QJsonDocument jsonDoc = QJsonDocument::fromJson(inputData.toUtf8());
        QJsonObject jo = jsonDoc.object();
        QJsonValue value = jo.value(QString(name));
        value = value.toBool(updateVal);
        jo.value(QString(name)) = jo.value(name).toBool(updateVal);
        value = jo.value(QString(name));
        value = value.operator =(updateVal);
        value = updateVal;
    

    // QJsonValue subobj = item[name];
    // subobj = updateVal;

    // item[name] = updateVal;
    configFile.write(jsonDoc.toJson());
    configFile.close();
    }

    return 0;
    

    }
    @

    ...and successfully compiled it with MSVC 2013 64-bit + Qt 5.3.0 beta, as well as MinGW 4.8 32-bit + Qt 5.2.1. The only issues I encountered were warnings about unused variables/parameters.

    There's nothing invalid with your code, as far as I can see.

    Perhaps some binary files simply got corrupted -- Try starting a new project and creating a minimal example.



  • LOL... I swear I tried that too... But Ill give it another shot



  • your code seems like you are doing the same thing over and over... granted Im fairly rusty with my C++ but it seems like 5 lines of code to do where a single [object Object] = updateVal@ should suffice. That doesnt seem efficient to me. Ill let you know if it works


  • Moderators

    [quote author="doozii" date="1395837642"]your code seems like you are doing the same thing over and over... granted Im fairly rusty with my C++ but it seems like 5 lines of code to do where a single [object Object] = updateVal@ should suffice. That doesnt seem efficient to me. Ill let you know if it works[/quote]That's your code -- I simply moved it into main() and un-commented lines.

    My main point was this: There is no compilation error. All of the different ways to assign something to QJsonValue are valid.

    (The actual code I would use is in my first reply, just below your original post)



  • ohhh I see. yeah I was trying to just use [object Object] = updateVal;@ I left all the commented out lines in to show what i had tried.



  • So I believe you are correct. I missed your comment about not being able to initialize with pointers and I was passing a pointer. Did not realize it wouldnt work with a reference. I tried again and all of the things I tried seem to work now.

    Thank you so much for working through this with me.


  • Moderators

    I'm glad you've found a solution :)

    All the best with your project!



  • I got this to compile but there is no value getting written to the QJSonValue and/or the value isnt getting written back to the QJsonDocument. So when I do the [object Object] = val@ and I look at the value variable... its empty.

    I wish there was example code for this somewhere or someone would write a book and include JSON handling in it.


  • Moderators

    It's not quite a book, but see the official unit tests for a comprehensive suite of JSON assignments/manipulations: http://code.woboq.org/qt5/qtbase/tests/auto/corelib/json/tst_qtjson.cpp.html

    How did you look at the QJsonValue?



  • i did a qWarning() << value.toString(); and a qWarning() << value; Also tried qWarning() << jo[name] and a host of others. All returned as ""


  • Moderators

    Code:
    @
    #include <QJsonDocument>
    #include <QJsonObject>
    #include <QFile>
    #include <QDebug>

    int main()
    {
    QFile file("test.json");
    if (file.open(QFile::ReadOnly|QFile::Text))
    {
    QByteArray jsonText = file.readAll();
    file.close();

        QJsonDocument doc = QJsonDocument::fromJson(jsonText&#41;;
        qDebug() << doc;
    
        QJsonObject obj = doc.object();
        qDebug() << obj;
    
        QJsonValue val = obj["dblValue"];
        qDebug() << val;
    
        qDebug() << "-----";
    
        val = 1.61803;
        qDebug() << val;
    
        obj["dblValue"] = val;
        qDebug() << obj;
    
        doc.setObject(obj);
        qDebug() << doc;
    
        if (file.open(QFile::WriteOnly|QFile::Text))
        {
            file.write(doc.toJson());
            file.close();
        }
    }
    
    return 0;
    

    }
    @

    Input file:
    @
    {
    "boolValue": true,
    "dblValue": 3.14159,
    "strValue": "Hello!"
    }
    @

    Output:
    @
    QJsonDocument({"boolValue":true,"dblValue":3.1415899999999999,"strValue":"Hello!"})
    QJsonObject({"boolValue":true,"dblValue":3.1415899999999999,"strValue":"Hello!"})
    QJsonValue(double, 3.14159)

    QJsonValue(double, 1.61803)
    QJsonObject({"boolValue":true,"dblValue":1.6180300000000001,"strValue":"Hello!"})
    QJsonDocument({"boolValue":true,"dblValue":1.6180300000000001,"strValue":"Hello!"})
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.