Storing a JSON object



  • Hi,

    I am stuck with my JSON object. I am able to get a JSON response from a server, see the code below. But I am unable to work with the retuned JSON object.

    function get(url, task, id) {
        var xhr = new XMLHttpRequest();
        xhr.open("GET",url,true);
        xhr.onreadystatechange = function(){
        if ( xhr.readyState == xhr.DONE){
                if ( xhr.status == 200){
                    var jsonObject = JSON.parse(xhr.responseText)
                    if(task === "service"){
                        console.log(JSON.stringify(jsonObject)) // correct output of the object
                        return jsonObject
                    }
                }
            }
        }
        xhr.send();
    }
    

    In a QML file I try to put the object in a property:

    property var event: Parser.get(accountModel.get(0).urlRead + "/api/app/v1/details.php?id="+ eventModel.get(eventModel.activeEvent).i +"&sids="+accountModel.get(0).sids, "service", 0)
    
    Label {
          text: eventPage.event["t"]
    }
    // [W] unknown:57 - file:///.../EventPage.qml:57: TypeError: Cannot read property 't' of undefined
    

    The property event is always undefined. Is it not possible to put a JSON object in a property or am I just doing something wrong?



  • This post is deleted!


  • @Sikarjan
    Result of get() function is undefined because you do not return anything from it.
    You do return event value, but in a callback function. You should update your property value directly from callback.



  • @Roumed

    Thanks for looking at my question but I do not understand your answer. Why is return jsonObject not returning anything?



  • @Sikarjan
    Okey, let's try another way.
    Fix your code like this

    ...
    xhr.send();
    return { t: "yep" };
    }
    

    This is return from your function get().

    Where you try to return it is another function, called from another place, with processing it's return value at place, where it has called asynchronously.



  • ha i didn't even notice the lambda function() declaration due to the lack of indentation there :D But yes, the get(...) function you wrote doesn't have a return statement, therefore you aren't getting anything from it.



  • Also a thought: Since XMLHttpRequest will execute the query most likely asynchronously, you won't get your reply with JSON when the get() function finishes. Use your callback function to set the property event there(this means that the property also must be visible from there), like this:

    function get(url, task, id, eventHolder) {
        var xhr = new XMLHttpRequest();
        xhr.open("GET",url,true);
        xhr.onreadystatechange = function(){
        if ( xhr.readyState == xhr.DONE){
                if ( xhr.status == 200){
                    var jsonObject = JSON.parse(xhr.responseText)
                    if(task === "service"){
                        console.log(JSON.stringify(jsonObject)) // correct output of the object
                        //return jsonObject
                        eventHolder.event = jsonObject
                    }
                }
            }
        }
        xhr.send();
    }
    
    Item {
       id: myItem
       property var event
       Component.onCompleted: { Parser.get(accountModel.get(0).urlRead + "/api/app/v1/details.php?id="+ eventModel.get(eventModel.activeEvent).i +"&sids="+accountModel.get(0).sids, "service", 0, myItem)
       }
    }
    


  • You can use jsonCache.com or myjson.com to test you function. They are both easy to use and very usefull.

    Regards,
    NNCU



  • Thanks for all your suggestions. I still do not 100 % the problem but I solved it similar to Jagh's suggestion. In stead of the line

    eventHolder.event = jsonObject
    

    I assign the jsonObject to a parameter in my main.qml. This variable is visible in all other pages of my program.

    It still baffles me that I can assign the object to a variable but not return it. I see that XMLHttpRequest works asynchronously and that get will be finished first but the rest I do not understand.



  • @Sikarjan the key problem i think here is to understand, what happens when functions are treated as first class citizens. C++ does this too(with lambda syntax for instance), but it is way more common to see in JavaScript, a language that has functional roots.

    In this example, we actually have 2 functions: one that is called get(url, task, id), and one that doesn't have a name(lambda function), its declaration begins with function(){... on line 4. To see it better, you could write the program from your first post as

    function onReadyState(xhr, task) {
        if ( xhr.readyState == xhr.DONE){
                if ( xhr.status == 200){
                    var jsonObject = JSON.parse(xhr.responseText)
                    if(task === "service"){
                        console.log(JSON.stringify(jsonObject)) // correct output of the object
                        return jsonObject
                    }
                }
            }
       }
    
    function get(url, task, id) {
       var xhr = new XMLHttpRequest()
       xhr.open("GET", url, true)
       xhr.onreadystatechange = onReadyState.bind(null, xhr, task)
       xhr.send()
    }
    

    As you can see here, you only have return statement in the first function(but you only directly call get) The onReadyState is not called in this code, .bind() only does here partial function application(basically the same as std::bind in C++).

    JavaScript has quite good support for functional-style programming, and professionals use this extensively. If in C++ it's very rarely that you encounter something like an std::function<void(int, string)> type, use of functional idioms in JavaScript is very common place. You will get used to them in time.



  • Thanks again for the explanation. I wish I had more time to learn programming correctly...


Log in to reply
 

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