Difference between toJSON() and JSON.Stringify()
JavascriptJsonbackbone.jsJavascript Problem Overview
> if you need to read or clone all of a model’s data attributes, use its > toJSON() method. This method returns a copy of the attributes as an > object (not a JSON string despite its name). (When JSON.stringify() is > passed an object with a toJSON() method, it stringifies the return > value of toJSON() instead of the original object. The examples in the > previous section took advantage of this feature when they called > JSON.stringify() to log model instances.)
http://addyosmani.github.io/backbone-fundamentals/#backbone-basics
Can anyone tell me the difference between both these ways of representing an object
in JSON
notation. I am just confused whether these to achieve the same or there is a difference.
Javascript Solutions
Solution 1 - Javascript
From the fine manual:
> toJSON behavior
>
> If an object being stringified has a property named toJSON
whose value is a function, then the toJSON
method customizes JSON stringification behavior: instead of the object being serialized, the value returned by the toJSON
method when called will be serialized.
This is why Backbone uses the toJSON
method for serialization and given a model instance called m
, you can say things like:
var string = JSON.stringify(m);
and get just the attributes out of m
rather than a bunch of noise that your server won't care about.
That said, the main difference is that toJSON
produces a value (a number, boolean, object, ...) that gets converted to a JSON string whereas JSON.stringify
always produces a string.
The default Backbone toJSON
is simply this (for models):
return _.clone(this.attributes);
so m.toJSON()
gives you a shallow copy of the model's attributes. If there are arrays or objects as attribute values then you will end unexpected reference sharing. Note that Backbone.Model#clone
also suffers from this problem.
If you want to safely clone a model's data then you could send it through JSON.stringify
and then JSON.parse
to get a deep copy:
var data = JSON.parse(JSON.stringify(model_instance));
var cloned_model = new M(data);
where model_instance
is your instance of the Backbone model M
.
Solution 2 - Javascript
-
JSON.stringify()
- Any valid JSON representation value can be stringified.The
JSON.stringify(..)
utility will automatically omitundefined
,function
, andsymbol
values when it comes across them. If such a value is found in anarray
, that value is replaced bynull
(so that the array position information isn't altered). If found as a property of anobject
, that property will simply be excluded.JSON stringification has the special behavior that if an
object
value has atoJSON()
method defined, this method will be called first to get a value to use for serialization. -
toJSON()
- to a valid JSON value suitable for stringification.One example,
JSON.stringify()
anobject
with circular reference in it, an error will be thrown.toJSON()
can fix it as following.var o = { }; var a = { b: 32, c: o }; // circular reference o.d = a; // JSON.stringify( a ); // an error caused by circular reference // define toJSON method a.toJSON = function() { return { b: this.b }; }; JSON.stringify( a ); // "{"b":32}"
Solution 3 - Javascript
I'm also reading Addy Osmani's Developing backbone.js application, and I have the same question. I figured out by trying his example (the todo list) in the console.
var Todo = Backbone.Model.extend({
defaults:{
title:"",
completed:false
}
});
var todo1 = new Todo();
console.log(todo1.toJSON())
//The console shows
//Object {title: "finish your assignment", completed: false}
console.log(JSON.stringify(todo1))
//The console shows
//{"title":"finish your assignment","completed":false}