1

I'm trying to parse the following JSON returned from a server:

{
"plant_1":{
    "name":"agi_1",
    "growth":[{"d":0,"m":20,"w":2,"n":"10"}]},
"plant_2":{
    "name":"agi_2",
    "growth":[{"d":0,"m":20,"w":2,"n":"20"}]},
"plant_3":{
    "name":"agi_3",
    "growth":[{"d":0,"m":20,"w":2,"n":"30"}]},
"plant_4":{
    "name":"agi_4",
    "growth":[{"d":0,"m":20,"w":2,"n":"40"}]},
"plant_5":{
    "name":"agi_5",
    "growth":[{"d":0,"m":20,"w":2,"n":"50"}]}
}

(code formatted for ease of reading, there's no newline char)

Directly parsing the JSON returns the following object :

enter image description here

As you can see, plant_1.growth is empty, while the others have the corresponding object in the array.

Copying the above string and doing JSON.parse on the string (e.g. JSON.parse('string')) works fine and returns the correct model.

I have no idea what's going on, as the JSON is valid. Any idea how to recover the model correctly?

EDIT 1

I'm using Express server and Mongoskin to query the Mongo database and return the requested data. Below is the DB query code :

db.collection('plants').find({owner : owner}, function(err, result) {
    if(err) throw err;

    var idx = 1;
    result.each(function(err, doc) {

        if(doc != null) {

            obj['plant_' + idx] = {
                name : doc.name,
                growth : doc.growth 
            }

            idx = idx + 1;

        } else {

            console.log(JSON.stringify(obj));
            res.send(JSON.stringify(obj));

        }

    });

});

result of console.log(JSON.stringify(obj)) :

{"plant_1":{"name":"agi_1","growth":[{"d":0,"m":20,"w":2,"n":"10"}]},"plant_2":{"name":"agi_2","growth":[{"d":0,"m":20,"w":2,"n":"20"}]},"plant_3":{"name":"agi_3","growth":[{"d":0,"m":20,"w":2,"n":"30"}]},"plant_4":{"name":"agi_4","growth":[{"d":0,"m":20,"w":2,"n":"40"}]},"plant_5":{"name":"agi_5","growth":[{"d":0,"m":20,"w":2,"n":"50"}]}}

EDIT 2

Code used to request and process request

    // Get plants data synchronously
var conn = new XMLHttpRequest();
conn.open("POST", "get-plants", false);

conn.setRequestHeader("Content-type", "application/json");
conn.onreadystatechange = function() {

    console.log(conn.responseText)   // Line 53
    var response = JSON.parse(conn.responseText);
    console.log(response);          // Line 55

    if(conn.readyState == 4 && conn.status == 200) { 

        if(response != null) {

            thatGame.plants = response;

        } else {
            // empty
            console.log('invalid');
        }
    }

};  
conn.send(JSON.stringify({owner : game.state.states['Main'].user}));

console.log(this.plants.plant_1);    // Line 74

And a screenshot of browser console.

enter image description here

Anugerah Erlaut
  • 990
  • 13
  • 23
  • 1
    Please post your code – baao Sep 14 '15 at 23:27
  • How do you know that exactly this data you posted is returned from the server? – Felix Kling Sep 14 '15 at 23:29
  • 2
    I can't see any issue with parsing that JSON string. I just ran it in my console and plant_1.growth isn't empty. See screenshot: http://i.imgur.com/keUx28C.jpg – Jared Sep 14 '15 at 23:31
  • 1
    How is the JSON being loaded from the server. When you inspect the call in the server, do you see what you think you are returning? – epascarello Sep 14 '15 at 23:34
  • Are you assigning some values to this object? If you are overwriting it in somewhere it might lead to this problem... – Venkatesh Nadar Sep 14 '15 at 23:34
  • 1
    Unrelated, but `res.send(JSON.stringify(obj))` is not as good as `res.json(obj)` (clearer, shorter, also sets your content type correctly). – Amadan Sep 15 '15 at 00:34
  • What does your Developer Tools Network panel say, which version is actually transmitted? – Amadan Sep 15 '15 at 00:35
  • @Amadan I'm sending a POST XHR request to `/get-plants` which returns correctly (status 200). `console.log(conn.responseText)` returns the correct JSON above. What's baffling me is why is `JSON.parse` not returning the object in the `plant_1`'s array while correctly returning the others, – Anugerah Erlaut Sep 15 '15 at 00:49
  • @FelixKling that's the baffling part :) I ran the returned JSON string using console's `JSON.parse` and returns the object correctly. However, a direct call to `JSON.parse(conn.responseText)` from the XHR query is missing an object in `plant_1`'s array – Anugerah Erlaut Sep 15 '15 at 00:53
  • put `debugger;` immediately after `console.log(JSON.parse(conn.responseText));` and verify that the object is correct immediately after the parse. You might be changing the object later, and `console.log` sometimes takes a bit of time (so your rendered object is different from the time when you called `console.log`). – Amadan Sep 15 '15 at 00:53
  • For example, test this in console: `var obj = ....; console.log(obj); o.plant_1.growth = [];` - it will almost certainly report that `o.plant_1.growth` is empty, even though you are modifying it after `console.log`. So if you want to see exact data in the object at that moment, either stop the program using `debugger`, or print `JSON.stringify(obj)`, so you get a string that won't change while being rendered. (Just guessing, but you changing the object after `console.log` is the only thing that I can think of.) – Amadan Sep 15 '15 at 00:55
  • @Amadan I think you're correct. I've updated the question with result after adding `debugger;` after `console.log(JSON.parse(conn.responseText))`. Putting `debugger` after `console.log(JSON.parse(conn.responseText))` shows the correct properties, and I can pop the object in the array even when `console.log` says there's nothing in it. – Anugerah Erlaut Sep 15 '15 at 01:20
  • If you're popping from the array, that's the very reason there's nothing in it. :) `console.log` is just showing you the future state. – Amadan Sep 15 '15 at 01:26
  • @Amadan ohh.. okay.. I just knew that. I thought `console.log` would post the current status of the object. Thanks for the help! :) – Anugerah Erlaut Sep 15 '15 at 01:30

0 Answers0