cloning a json object

1,796 views
Skip to first unread message

Angelo Chen

unread,
Jan 21, 2012, 9:07:38 PM1/21/12
to nodejs
Hi,

How to clone a json object in node 0.6x ? Thanks

Angelo

ben

unread,
Jan 21, 2012, 10:01:12 PM1/21/12
to nod...@googlegroups.com
Try this, 
https://github.com/dreamerslab/node.extend

a port of jQuery extend to node.js package

Mark Hahn

unread,
Jan 21, 2012, 10:18:07 PM1/21/12
to nod...@googlegroups.com
Underscore has everything you need.

 

Jake Verbaten

unread,
Jan 22, 2012, 8:36:12 AM1/22/12
to nod...@googlegroups.com
var clone = JSON.parse(JSON.stringify(o));
// or
var clone = {};
Object.getOwnPropertyNames(o).forEach(function (name) {
  clone[name] = o[name];
});



Angelo

--
Job Board: http://jobs.nodejs.org/
Posting guidelines: 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 post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to
nodejs+un...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en

Jann Horn

unread,
Jan 22, 2012, 8:39:18 AM1/22/12
to nod...@googlegroups.com
2012/1/22 Jake Verbaten <ray...@gmail.com>:
> var clone = JSON.parse(JSON.stringify(o));

Probably slow.


> var clone = {};
> Object.getOwnPropertyNames(o).forEach(function (name) {
>   clone[name] = o[name];
> });

Wrong, that's a shallow copy.

billywhizz

unread,
Jan 22, 2012, 10:25:03 AM1/22/12
to nodejs
it would be really nice if v8/javascript had a fast way of cloning an
object just by doing a memory copy behind the scenes or something like
this. i've encountered a lot of situations where i'd like to be able
to clone an existing object but haven't been able to do so because
it's so inefficient. does anyone know if there are plans to do this in
v8/js?

On Jan 22, 1:39 pm, Jann Horn <jannh...@googlemail.com> wrote:
> 2012/1/22 Jake Verbaten <rayn...@gmail.com>:

Mark Hahn

unread,
Jan 22, 2012, 1:58:27 PM1/22/12
to nod...@googlegroups.com
>   > var clone = JSON.parse(JSON.stringify(o)); 

Doesn't work with dates and functions.  Use _.clone.

Mark Hahn

unread,
Jan 22, 2012, 2:02:46 PM1/22/12
to nod...@googlegroups.com
just by doing a memory copy behind the scenes 

Unfortunately objects and their properties are stored in a much more complex way.  Doing a clone in V8 would be faster, but involve the same logic as doing it in Javascript.  What you are asking for is a new Object.clone() method..  For that you need to go to the standards committee.

Scott González

unread,
Jan 22, 2012, 2:30:42 PM1/22/12
to nod...@googlegroups.com
On Sun, Jan 22, 2012 at 1:58 PM, Mark Hahn <ma...@hahnca.com> wrote:
>   > var clone = JSON.parse(JSON.stringify(o)); 

Doesn't work with dates and functions.  Use _.clone.

The question was about the mythical "json object." Presumably the question is about a JavaScript object that can actually be represented by JSON, though it's not actually clear.

Jake Verbaten

unread,
Jan 22, 2012, 2:44:14 PM1/22/12
to nod...@googlegroups.com
> var clone = JSON.parse(JSON.stringify(o));

Probably slow.

Horribly slow. However stringifying is the most sensible way to pass clones around across processes or databases
 


> var clone = {};
> Object.getOwnPropertyNames(o).forEach(function (name) {
>   clone[name] = o[name];
> });

Wrong, that's a shallow copy.

Wrong, requiring deep clones is a data structure design mistake. Seriously deep clones are painful as heck, try to avoid them whenever possible.

> it would be really nice if v8/javascript had a fast way of cloning an
object just by doing a memory copy behind the scenes or something like
this. i've encountered a lot of situations where i'd like to be able
to clone an existing object but haven't been able to do so because
it's so inefficient. does anyone know if there are plans to do this in
v8/js?

Deep cloning arbitary javascript objects is a difficult problem to solve. It should be possible to implement a fast clone algorithm for deep copying the JSON subset though, this would be a good topic for es-discuss.


> Doesn't work with dates and functions.  Use _.clone.

Works on dates if you store them as timestamps ;) cloning functions is madness.

Mark Hahn

unread,
Jan 22, 2012, 2:52:45 PM1/22/12
to nod...@googlegroups.com
Deep cloning arbitary javascript objects is a difficult problem to solve.  

It's easy if you use _.clone().  (I'm sorry if I'm a broken record but nobody seems to take underscore seriously.  It's the second most-used module.)

Wrong, requiring deep clones is a data structure design mistake.

That's silly.  If you need a deep clone then you need a deep clone.  I use them all the time.

Of course it's wrong if it includes a socket or something.

Jake Verbaten

unread,
Jan 22, 2012, 4:26:07 PM1/22/12
to nod...@googlegroups.com
Deep cloning arbitary javascript objects is a difficult problem to solve.  

It's easy if you use _.clone().  (I'm sorry if I'm a broken record but nobody seems to take underscore seriously.  It's the second most-used module.)

_.clone returns a clone with the wrong [[Prototype]] (for custom [[Prototype]]'s), yes it has some value as a utility but it is limited. Of course in this case if it's a JSON object it doesn't matter. Note when I say "arbitary objects" I also mean "How do you clone proxies, closures and private state?"
 

Wrong, requiring deep clones is a data structure design mistake.

That's silly.  If you need a deep clone then you need a deep clone.  I use them all the time.

Agreed, I was being rather silly.

Note I started a thread on es-discuss about having a native way to efficiently deep clone some subset of objects ( https://mail.mozilla.org/pipermail/es-discuss/2012-January/019915.html )

Mark Hahn

unread,
Jan 22, 2012, 6:09:46 PM1/22/12
to nod...@googlegroups.com
_.clone returns a clone with the wrong [[Prototype]] 

Hmm.  The question is whether you are cloning an object's properties or the actual typed object.  I have not run into the need for cloning a typed object.  It would be easy to switch prototypes after the clone.  It would also be easy to add a flag for this to underscore.

>   Note when I say "arbitary objects" I also mean "How do you clone proxies, closures and private state?" 

I'd love to have access to closures.  Is that being considered for future JS specs?  For now I have to live with plain objects since I only write code that works on both the server and client where possible.  I find it too hard to remember which environment I'm in and what is allowed.

billywhizz

unread,
Jan 22, 2012, 7:55:12 PM1/22/12
to nodejs
> It should be possible to implement a fast clone algorithm for deep copying
> the JSON subset though, this would be a good topic for es-discuss.

yes. i should have said that i was thinking of cloning simple/json
objects. i totally understand why "deep" cloning is not going to be
possible. i was thinking of being able to clone a json object so i can
pass a copy of it to be operated on while leaving the original
untouched. if you can point me in the direction of any reading i can
do around that or at some v8 source that might be enlightening, i'd be
very interested.

Mark Hahn

unread,
Jan 22, 2012, 8:32:51 PM1/22/12
to nod...@googlegroups.com
 i totally understand why "deep" cloning is not going to be possible.  

Why is this impossible?

Scott González

unread,
Jan 22, 2012, 9:06:10 PM1/22/12
to nod...@googlegroups.com
On Sun, Jan 22, 2012 at 7:55 PM, billywhizz <apjo...@gmail.com> wrote:
if you can point me in the direction of any reading i can
do around that or at some v8 source that might be enlightening, i'd be
very interested.

You'll want to find an area of v8 where a structured clone is required. Storage events (local/sessionStorage) probably require structured clones.

http://www.w3.org/TR/html5/common-dom-interfaces.html#safe-passing-of-structured-data

Dobes

unread,
Jan 23, 2012, 12:18:12 AM1/23/12
to nodejs
If you're using sugar.js it has a clone utility method,
Object.deepClone().

Also the other libraries (underscore or node.extend) already mentioned
will do the job well, too, I'm sure.

Don't worry too much about the "controversy" of deep cloning in this
discussion; if you're just trying to clone an object that you parsed
from a JSON string already you don't have to worry about prototypes,
dates, functions, closures, or cyclic data structures as these are not
representable in JSON.

If performance isn't critical and you don't want to use a library the
JSON.parse(JSON.stringify(obj)) version is quite straightforward and
will work for any object that you can represent in JSON.

For those who want to copy "arbitrary objects" there's a concept of
eval(uneval(obj)) in other javascript engines for deep copy but I
don't think that is available in node at this time. There's a module
for that but I assume there's probably a number of cases that it will
break down on; it probably won't not create a fresh copy of enclosed
variables as that is probably impossible to do properly as the
relationships between functions start to get a bit complicated.
https://github.com/chakrit/node-uneval/blob/master/node-uneval.js

AJ ONeal

unread,
Jan 23, 2012, 12:42:25 AM1/23/12
to nod...@googlegroups.com
> var clone = JSON.parse(JSON.stringify(o));

Probably slow.

DEFINITELY slow (if you're coping 11,381 file stat objects on ARM)
I did that tonight (not the production solution of course, but it works).


Probably fast enough for simple (< 10,000 objects on x86) use cases.

The part that is slow is the `stringify`. It eats memory like a beast too.
Or at least it did in v0.4.0. I haven't rerun my benchmarks since then.
But try parsing and stringifying a 26mb json database on ARM (again, not the production solution, but works for a prototype).

I would imagine that the streaming JSON libraries are better, but I haven't tested yet.

Phoscur

unread,
Jan 23, 2012, 1:58:13 AM1/23/12
to nod...@googlegroups.com
_.clone returns a clone with the wrong [[Prototype]] 

Hmm.  The question is whether you are cloning an object's properties or the actual typed object.  I have not run into the need for cloning a typed object.  It would be easy to switch prototypes after the clone.  It would also be easy to add a flag for this to underscore.
How do you switch prototypes? __proto__ is not available crossplatform.


Interesting topic,  I just had a situation where I used _.clone instead of Object.create.
You know, that Object.create kind of creates a copy?
I wanted to return a collection, but enforce setters so to prevent manipulation, I decided to return a clone instead of the original. I went with _.clone() because it seemed saver.
Now I'm not sure which "clone" function is best to use in which case.

Object.create(obj) creates a new object with the given obj as prototype. So the returned object is basically a clone of the original, when you modify it, the original is untouched.
Also it is fast, as it is part of the es specification and it just creates an empty object with a prototype pointer.
This function can create a lot of oo-javascript magic, completely replacing classes with prototypal inheritance.



>   Note when I say "arbitary objects" I also mean "How do you clone proxies, closures and private state?" 

I'd love to have access to closures.  Is that being considered for future JS specs?  For now I have to live with plain objects since I only write code that works on both the server and client where possible.  I find it too hard to remember which environment I'm in and what is allowed.
I don't understand. Isn't privat state ment to be privat, so by definition not accessable and thereby not available for cloning? Some goes for closures holding closure..
If you want an object with privat variables and bound methodes to be cloned you have to use it's constructor again.

Jann Horn

unread,
Jan 23, 2012, 2:44:01 AM1/23/12
to nod...@googlegroups.com

Streaming JSON libs are several times slower. Just do a recursive copy.

Posting guidelines: https://github.com/joyent/node/wiki/Mai...

ollym

unread,
Jan 23, 2012, 7:17:44 AM1/23/12
to nodejs
You're almost there. Can't believe there is so much discussion over
the most basic of tasks. The proper way to clone an object in ECMA5:

Standalone version:
https://gist.github.com/1662767

Toolkit source:
https://github.com/ollym/toolkit/blob/master/lib/object.js#L455-481

This means changes made down the prototype chain will continue to
bubble up which is important in many cases. Note this is only a
shallow clone, i'd be surprised if you ever have a genuine reason to
perform a deep clone but if you do it wouldn't be too difficult to
extend the logic of the examples I've given above.
> <http://groups.google.com/group/nodejs?hl=en?hl=en>

Scott González

unread,
Jan 23, 2012, 8:17:11 AM1/23/12
to nod...@googlegroups.com
On Mon, Jan 23, 2012 at 7:17 AM, ollym <oliver...@kohark.com> wrote:
i'd be surprised if you ever have a genuine reason to
perform a deep clone

There are plenty of cases where you want to provide data, say in an event, but you don't want the listeners to be able to modify the actual objects you're working with.

Mark Hahn

unread,
Jan 23, 2012, 2:08:03 PM1/23/12
to nod...@googlegroups.com
Same goes for closures holding closure.. 

What's wrong with treating a closure as an object?  A closure is an accessible object in many functional languages.  It is a missing feature in JS.

I often use a closure instead of an class-based object.  They are very easy to setup and use.

Jann Horn

unread,
Jan 24, 2012, 12:29:52 PM1/24/12
to nod...@googlegroups.com
2012/1/23 Mark Hahn <ma...@hahnca.com>:

>>  Same goes for closures holding closure..
>
> What's wrong with treating a closure as an object?  A closure is an
> accessible object in many functional languages.  It is a missing feature in
> JS.

Oh, that'd be awesome. :)

Phoscur

unread,
Jan 24, 2012, 5:50:36 PM1/24/12
to nod...@googlegroups.com
Can you describe a situation where you'd use that in javascript?

Mark Hahn

unread,
Jan 24, 2012, 6:31:17 PM1/24/12
to nod...@googlegroups.com
>  Can you describe a situation where you'd use that in javascript? 

Basically you could use it anywhere you use an OOPS object.  For example you could pass it to a callback so the callback could access vars in the closure.

# this is equivalent to a Service class definition
Service = (cb) ->
  x = 9
  func = -> 'hello'
  closure= magicClosureGetter()
  cb closure

# this is equivalent to instantiation of a Service object
Service (  service )  ->
    console.log service.func()
    console.log service.x

Mark Hahn

unread,
Jan 24, 2012, 6:33:55 PM1/24/12
to nod...@googlegroups.com
I screwed that up.  What I called a closure would actually just be the local scope, which is another object I wish I had access to.  I've got to get back to my real job, but I hope you get the idea.

Phoscur

unread,
Jan 24, 2012, 10:26:55 PM1/24/12
to nod...@googlegroups.com
Thanks,
I understand now. But as you say yourself, there is already a way to do this in JavaScript, it's just a matter of the style.

Axel Kittenberger

unread,
Jan 25, 2012, 4:23:01 AM1/25/12
to nod...@googlegroups.com
Or in my case I want to remember an event for casual consistency
reasons, but the caller does not like it, when the data structure it
provided is suddendly deepFrozen after the call.
Reply all
Reply to author
Forward
0 new messages