Alternative to JSON that CAN store JS functions and such?

fuzzybabybunny

Moderator<br>Digital & Video Cameras
Moderator
Jan 2, 2006
10,455
35
91
Really. It's such a pain in the ass if you're working 100% in JavaScript anyway.

If you're doing your entire stack in JS it would be SO nice to just be able to store everything in their original data types so you don't have to mess around with the data types when you retrieve them again.

Numbers instead of strings.
Ability to store functions.
Ability to store constructors ( new Date() ).

Right now if I have an object like:

Code:
var myOrder = {
  dateCreated: new Date();
  items: [
    // all items
  ],
  totalPrice: function(){
    // return the total price of everything using this.items in a loop
  },
}

it would be nice to just store it into my DB and maybe the user's browser localstorage just like that.

But instead everything needs to be a string and functions are forbidden.

When you retrieve the data again you have to do extra work to convert the items back into their intended data type, add the original functions back into the object, parse your own data, etc.
 

Ken g6

Programming Moderator, Elite Member
Moderator
Dec 11, 1999
16,417
4,186
75
Well, if you stored that entire object as a string in your DB, you could use eval() to restore the object.

But eval, being powerful, is dangerous. You need to ensure your "data" doesn't include malicious code before calling it.
 

Cogman

Lifer
Sep 19, 2000
10,283
134
106
I just want to add that this is a bad idea. Functionality should never be stored, it should only ever be part of the code itself. Storing and sharing functionality on purpose or accident is almost always a security issue.

Data should never be executed, and doubly so when it comes to data the client gives.

Further, it is a bad design. If you ever want to change functionality, you will curse the fact that you stored it off into the database.
 

purbeast0

No Lifer
Sep 13, 2001
53,163
6,038
126
yeah i'm not following why you would want to store that function either. why not just put it on the prototype of that object?
 

fuzzybabybunny

Moderator<br>Digital & Video Cameras
Moderator
Jan 2, 2006
10,455
35
91
So say that I have an object that stores a customer's order information. Items, prices, quantities, etc. I want to save this object to my DB?

It wouldn't be a good idea to have that object also have a totalPrice() function that loops through itself and returns the total price?
 

Cogman

Lifer
Sep 19, 2000
10,283
134
106
So say that I have an object that stores a customer's order information. Items, prices, quantities, etc. I want to save this object to my DB?

It wouldn't be a good idea to have that object also have a totalPrice() function that loops through itself and returns the total price?

Correct, that would be a bad idea.

What if price changes? What if you want to differentiate between outstanding bills vs payed bills? What if you decide to calculate price or totaling differently? You now have this bit of functionality stored in your db that you have to extract out each object to update it with the correct code and then push that back into the database.

What if you decide that "You know what, javascript for my backend server worked, but I need a more safe and faster language."

That isn't something you ever want to deal with, trust me.
 

uclabachelor

Senior member
Nov 9, 2009
448
0
71
Really. It's such a pain in the ass if you're working 100% in JavaScript anyway.

If you're doing your entire stack in JS it would be SO nice to just be able to store everything in their original data types so you don't have to mess around with the data types when you retrieve them again.

Numbers instead of strings.
Ability to store functions.
Ability to store constructors ( new Date() ).

Right now if I have an object like:

Code:
var myOrder = {
  dateCreated: new Date();
  items: [
    // all items
  ],
  totalPrice: function(){
    // return the total price of everything using this.items in a loop
  },
}

it would be nice to just store it into my DB and maybe the user's browser localstorage just like that.

But instead everything needs to be a string and functions are forbidden.

When you retrieve the data again you have to do extra work to convert the items back into their intended data type, add the original functions back into the object, parse your own data, etc.

This sounds more like a design problem than a limitation.

So say that I have an object that stores a customer's order information. Items, prices, quantities, etc. I want to save this object to my DB?

It wouldn't be a good idea to have that object also have a totalPrice() function that loops through itself and returns the total price?

What if you have to modify that function later on? How many copies of that code will around? Isn't it better to have the backend return the totalPrice as part of the data? If that's not possible, then perform an ajax call within totalPrice to get the total instead.
 
Last edited:

jshepler

Junior Member
Oct 17, 2015
1
0
0
You can set the prototype of the deserialized object to your class to "re-attach" your functions. e.g.:

Code:
function someClass(i)
{
  this.someInt = i || 0;
  this.addOne = function()
  {
    this.someInt++;
    console.log(this.someInt);
  };
}

var fromClass = new someClass();


var fromDB = { someInt: 10};
Object.setPrototypeOf(fromDB, fromClass);
fromDB.addOne();
But that doesn't help if any of the properties are complex objects themselves. You could modify your constructors to take a data object to populate the properties. Even easier with an extend method.

Code:
function class1(data)
{
  var defaults = { int1: 0 };
  var model = $.extend(defaults, data);
  
  model.foo = function()
  {
    console.log("from class1: " + model.int1);
  };
  
  return model;
}

function class2(data)
{
  var defaults = { obj: null, int2: 0 };
  var model = $.extend(defaults, data);
  
  model.obj = new class1(model.obj);
  
  model.bar = function()
  {
    console.log("from class2: " + model.int2);
  };
  
  return model;
}

var fromDB = { obj: { int1: 42 }, int2: 10 };
fromDB = new class2(fromDB);

fromDB.bar();
fromDB.obj.foo();
 
Last edited: