Why does JSON object overwrites it's previously stored values?

I have defined JSON object "OBJ" with key "test" and it's value 0.

Then I iterate through for loop 10 times. First I push the current data of OBJ into msg.payload which is an array. I then assign new value for test, which is "i".

slika
In the end, I expect msg.payload to be [{"test": 0}, {"test": 1}, {"test": 2},...{"test": 9}].

Instead of that, the data of msg.payload is [{"test": 9}, {"test": 9}, {"test": 9},...{"test": 9}].

Why does this overwrite happen? For example, i tested the same thing with variable that holds integer. There i got the expected result, where the output changes from 0 to 9.

So is this just a normal property of JSON objects? If not, how could i store the data in payload, so that i get the expected output, not all values 9?

The JS experts will be along in a bit - but one thing that leaps out at me is your setting OBJ.text to the index counter i and not (as I think you want it to be) {"test":value_of_i}

1 Like

Javascript passes objects by reference so once you declared it outside the loop there is only one instance of the object and all you are doing inside is setting all of them to point to (refer to) the same object - so when you then set one of its properties it sets it for all - and the last thing you set the test to is 9 so they are all 9. If in doubt push the object you really want.

msg.payload.push( {"test":i} );

to create a new object for each one you want to push.

1 Like

I actually wanted it to store the index counter, just for the testing purposes. But thank you for that note.

Thank you for the explanation, works exactly as I wanted. I didn't know about the object references and all of what is going on behind the program.

I also found two more solutions for anyone facing similar problem.

First one is cloning message:

msg.payload.push(RED.util.cloneMessage(OBJ));

Second one is transforming an object into string and then turning it back into an object:

msg.payload.push(JSON.parse(JSON.stringify(OBJ)));

In both cases the output of "test" is changing from 0 to 9, just like I wanted.

both of those are long winded ways of achieving the same. The first is more "correct" but is less performant, whereas the second just forces it to be a new string object then back to a new parsed object... so two steps instead of one... so yes either are alternatives but just creating what you want at the time is faster and easier to read.

3 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.