Appending to array - Not working as expected

32 views
Skip to first unread message

Tippur

unread,
Aug 3, 2016, 5:08:29 PM8/3/16
to nodejs
I have a json object that has an array field

I want to take that object and break it into individual json objects.

For example { a:[ 'x', 'y'], rest: 'fdsf', ff: 'll' } should be broken into 

{ a: 'x', rest: 'fdsf', ff: 'll' } and { a: 'y', rest: 'fdsf', ff: 'll' }


Here is my code:
##################################

var str='{ \

        "a": ["x", "y"], \

        "rest": "fdsf", \

        "ff": "ll" \

}'

jsonstr=JSON.parse(str);

var payload=[];

if (Array.isArray(jsonstr['a'])){

        console.log("Is array");

        var payload=[];

        jsonstr['a'].forEach(function(item, index) {

                console.log(item);

                jsontemp=jsonstr;

                jsontemp.a=item;

                console.log(jsontemp);

                payload.push(jsontemp);

        });

}

console.log(payload);

##################################

Here is the output

[ { a: 'y', rest: 'fdsf', ff: 'll' },

  { a: 'y', rest: 'fdsf', ff: 'll' } ]


As you can see, the object appended to the final payload has the same element (payload.a)


What am I doing wrong?


- Shekar






Joshua Holbrook

unread,
Aug 3, 2016, 5:16:31 PM8/3/16
to nod...@googlegroups.com
It looks like jsontemp is a global variable here, due to the lack of a
'var', 'let' or similar.

fwiw adding 'use strict'; at the top of your file should make this
complain rather than silently doing what you don't want.

--Josh
> --
> Job board: http://jobs.nodejs.org/
> New group rules:
> https://gist.github.com/othiym23/9886289#file-moderation-policy-md
> Old group rules:
> https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
> ---
> You received this message because you are subscribed to the Google Groups
> "nodejs" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to nodejs+un...@googlegroups.com.
> To post to this group, send email to nod...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/nodejs/8275a391-bc72-4bba-a43f-a17be42f0d61%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Tippur

unread,
Aug 3, 2016, 8:45:00 PM8/3/16
to nodejs
Changed it to

##########

'use strict'

var str='{ \

        "a": ["x", "y"], \

        "rest": "fdsf", \

        "ff": "ll" \

}'


var jsonstr=JSON.parse(str);


var payload=[];


if (Array.isArray(jsonstr['a'])){


        console.log("Is array");


        var payload=[];


        jsonstr['a'].forEach(function(item, index) {


                console.log(item);

                var jsontemp=jsonstr;


                jsontemp.a=item;


                console.log(jsontemp);


                payload.push(jsontemp);



        });


}


console.log(payload);


####################


i get the same result.

Xy Wang

unread,
Aug 4, 2016, 1:03:44 AM8/4/16
to nodejs

var jsontemp = {}
jsontemp.a = item
jsontemp.rest = jsonstr.rest
jsontemp.ff = jsonstr.ff

payload.push(jsontemp)


var jsontemp  = jsonstr means both indicate to the same object, not a deeply copy

Ryan Graham

unread,
Aug 4, 2016, 1:04:26 AM8/4/16
to nodejs

In your code you are doing this:
var jsontemp=jsonstr;

This is not making a copy of jsonstr, it is making an alias that points to the same object. This means that later when you are modifying jsontemp.a you are also modifying jsonstr.a and when you push jsontemp on to your array, you are pushing a reference on to the list.

In other words, you are modifying jsonstr in place and then adding it to an array each time you do it.

~Ryan



For more options, visit https://groups.google.com/d/optout.
--

~Ryan

Ryan Schmidt

unread,
Aug 4, 2016, 1:05:29 AM8/4/16
to nod...@googlegroups.com

On Aug 3, 2016, at 7:43 PM, Tippur wrote:

> Changed it to
>
> ##########
> 'use strict'
>
> var str='{ \
>
> "a": ["x", "y"], \
>
> "rest": "fdsf", \
>
> "ff": "ll" \
>
> }'
>
>
>
> var jsonstr=JSON.parse(str);
>
>
>
> var payload=[];
>
>
>
> if (Array.isArray(jsonstr['a'])){
>
>
>
> console.log("Is array");
>
>
>
> var payload=[];
>
>
>
> jsonstr['a'].forEach(function(item, index) {
>
>
>
> console.log(item);
>
> var jsontemp=jsonstr;

Here, you're making jsontemp a reference to the same block of memory used by jsonstr. Later, when you modify jsontemp.a, it's the same as modifying jsonstr.a. Then later, when you push jsontemp onto the payload array, you're pushing a reference to that same jsontemp / jsonstr block of memory. Since that's in a forEach it happens multiple times, but each time, you're pushing a reference to the same block of memory onto the array, which is why when you print the array later, every item is the same, and has the values from the last loop iteration.

The fix is to make jsontemp an actual copy of jsonstr, with its own memory that you can modify independently, e.g.:

var jsontemp=Object.assign({}, jsonstr);
Reply all
Reply to author
Forward
0 new messages