0

I have been at this for hours and just can't get it quite right. I have an object with methods that works fine. I need to save it as a string using JSON.stringify and then bring it back as an object and still use the same methods.

function Workflow(){
  this.setTitle = function(newtitle){this.title = newtitle; return this;};
  this.getTitle = function(){return this.title;}; 
}

function testIn(){
  var workflow = new Workflow().setTitle('Workflow Test'); 
  Logger.log(workflow);//{title=Workflow Test}
  Logger.log(workflow.getTitle()); //Workflow Test

  var stringy = JSON.stringify(workflow);
  var newWorkflow = Utilities.jsonParse(stringy);
  Logger.log(newWorkflow); //{title=Workflow Test} 
                           //Looks like the same properties as above

  Logger.log(newWorkflow.getTitle());//Error can't find getTitle
}

I think I should prototype the new object but nothing seems to work. Please help I have very little hair left.

James Ferreira
  • 316
  • 1
  • 2
  • 11

4 Answers4

1

You need to copy the method to the new object:

newWorkflow.getTitle = workflow.getTitle;
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
0

you are losing your functions when you stringify and parse. if you have access to jquery, the $.extend is handy (if not, just copy&paste form jquery source)

here's a demo: http://jsfiddle.net/VPfLc/

karnyj
  • 1,182
  • 1
  • 9
  • 10
0

Serializing to JSON won't store executable code. It's being removed from your object when calling JSON.stringify. Your best bet is to make the object so it can be initialized when created.

function Workflow(){
  this.initialize = function(properties) { this.title = properties.title; }
  this.setTitle = function(newtitle){this.title = newtitle; return this;};
  this.getTitle = function(){return this.title;}; 
}

function testIn(){
  var workflow = new Workflow().setTitle('Workflow Test'); 
  Logger.log(workflow);//{title=Workflow Test}
  Logger.log(workflow.getTitle()); //Workflow Test

  var stringy = JSON.stringify(workflow);
  var newWorkflow = new Workflow().initialize(Utilities.jsonParse(stringy));
  Logger.log(newWorkflow); //{title=Workflow Test} 
                           //Looks like the same properties as above

  Logger.log(newWorkflow.getTitle());//Error can't find getTitle
}
funwhilelost
  • 1,990
  • 17
  • 20
  • Unfortunately you don't have jQuery.extend() to automatically add properties to your object in the initialize function but you can at least add them by hand here and retain much of the same code flow you started with. – funwhilelost Sep 26 '11 at 23:58
0

All you have to do is use call.

Workflow.call(newWorkflow);

EDIT:

If your actual Workflow() implementation sets any attributes to default values during its initilization then calling on your new json object will also reset those. Which is what I'm assuming is going on, without being able to look at your actual implementation code.

If that is the case, then you have two options.

1) Rather than blindly initilize your object (and assuming its empty), conditionally initilize your variables.

function Workflow(){
  this.setTitle = function(newtitle){this.title = newtitle; return this;};
  this.getTitle = function(){return this.title;}; 
  this.array = this.array || [];
}

for new empty objects. this.array will be null, and it'll be set to a new array. calling Workflow on a existing object that already has that property, it'll leave it alone.

2) Extract your methods into an Extension Module

function Workflow(){
  this.array = this.array || [];
  // Other work

  // Lastly include my method extensions.
  WorkflowMethodExtensions.call(this);
}

function WorkflowMethodExtensions(){
  this.setTitle = function(newtitle){this.title = newtitle; return this;};
  this.getTitle = function(){return this.title;}; 
}

Then use:

WorkflowMethodExtensions.call(newWorkflow);

to extend an existing object with those methods defined in the existion

J. Holmes
  • 18,466
  • 5
  • 47
  • 52