0

Or maybe even override some portion of JSON.parse to parse functions? This isn't time sensitive, I built work arounds in my code, but with the eval function, you would think that turning functions into strings and back would be a piece of cake.

  • What do you aim to achieve by stringify a function? – Mukund Goel Apr 15 '20 at 04:32
  • Sure, this is possible. `JSON.parse()` has a second parameter that allows manipulating the object after parsing. You need to determine how you'll identify a function vs. a regular string. – Brad Apr 15 '20 at 04:34
  • What would be a use-case for this? You only need JSON when you're transferring data from an environment to another. Then you'd need to create an interpreter on the receiving end too, functions are rarely interchangeable. Inside JS you can always use a live object containing methods. – Teemu Apr 15 '20 at 04:35
  • I have this "weapon" object, that has it's own attack function. Each weapon does it's own thing. I realized that I wouldn't ever need to save the current loadout because the characters never pickup or drop weapons. – Leif Messinger LOAF Apr 15 '20 at 05:28

2 Answers2

1

It's possible, but weird, and you of course wouldn't have access to any of the outer scope of the parsed function. Call toString to get the function's source code, trim out the brackets so you just have the function body, and have Function.prototype.toJSON return that. Then when parsing, call new Function on the string:

Function.prototype.toJSON = function() {
  // trim out beginning and end {}s
  return this.toString().match(/[^{]*(?=}$)/)[0];
};

const fn = () => {
  console.log('foo');
};
const json = JSON.stringify({
  str: 'str',
  fn
});
console.log(json);
const parsed = JSON.parse(json);
const parsedFn = new Function(parsed.fn);
parsedFn();

But there shouldn't be a need to do this in 99% of situations. Whatever the actual issue is, there's probably a more elegant solution.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • This is a potential XSS vector, don't use it with external data, including user input and your own database. – Teemu Apr 15 '20 at 05:27
0

I think no need to strip brackets. I use more simple code. It allows you to pass args to your function:

Function.prototype.toJSON = function() {  return this.toString(); };

const json = JSON.stringify({ 
  func: (a,b) => { console.log(a,b); },
  a: 1
});

const parsed = JSON.parse(json);

const parsedFunc = Function('return ' + parsed.func + ';')();

parsedFunc('hello','world');