8
votes

I have a few models that don't just contain basic data attributes, but they might have one or two attributes that hold another models object.

This has been okay, but now I want to call

myRootModel.toJSON()

and I've noticed that it doesn't call .toJSON on the other models in my model that I'm trying to call toJSON() on.

Is there a way to override backbone model .toJSON to go through all fields, recursively, whether they are basic attributes, sub-models or collections? If not, can I override toJSON in each model / collection?

I'm aware of backbone-relational, but I don't want to go that route - I'm not using fetch/save, instead our API returns responses that I adjust in the models parse function and simply invoke new MyRootModel(data,{parse:true}).

2
So you're not actually converting anything to JSON (i.e. a string), you're just using toJSON to serialize your data to plain objects and arrays? - mu is too short
I am indeed using toJSON get get plain objects and arrays, primarily so that BackBone view templates can iterate over them successfully without complications; using underscore templates I can invoke methods on my methods and collections but the advice from a recent London BackBone Meetup was not always convert to plain object (graphs) first. - Devology Ltd

2 Answers

16
votes

Here's a way you can achieve such a thing (there's maybe another way):

Backbone.Model.prototype.toJSON = function() {
  var json = _.clone(this.attributes);
  for(var attr in json) {
    if((json[attr] instanceof Backbone.Model) || (json[attr] instanceof Backbone.Collection)) {
      json[attr] = json[attr].toJSON();   
    }
  }
  return json;
};

http://jsfiddle.net/2Asjc/.

5
votes

Calling JSON.parse(JSON.stringify(model)) parses the model with all the sub-models and sub-collections recursively. Tried on Backbone version 1.2.3.