Home » JavaScript » Pass JavaScript function via JSON. Pitfall and solution.

About Oleg Varaksin

Pass JavaScript function via JSON. Pitfall and solution.

JSON is a lightweight data-interchange format. It is well readable and writable for humans and it is easy for machines to parse and generate. The most of JavaScript libraries, frameworks, plugins and whatever are configurable by options in JSON format.

Sometimes you have to parse a JSON string (text) to get a real JavaScript object. For instance, sometimes you have to read the whole JSON structure from a file and make it available on the client-side as an JavaScript object. The JSON text should be well-formed. Passing a malformed JSON text results in a JavaScript exception being thrown.

What does “well-formed” mean? A well-formed JSON structure consists of data types stringnumberobjectarrayboolean or null. Other data types are not allowed. An example:

{
    'name': 'Max',
    'address': {
        'street': 'Big Avenue 5',
        'zipcode': 12345,
        'country': 'USA'
    },
    'age': 35,
    'married': true,
    'children': ['Mike', 'John']
}

You see here string values for keys “name”, “street” and “country”, number values for “zipcode” and “age”, boolean value for “married”, object for “address” and array for “children”. But what is about JavaScript functions? Some scripts allow to pass functions as values. For instance as in some chart libraries:

{
    'margin': '2px',
    'colors': ['#FFFFFF', 'CCCCCC'],
    'labelFormatter': function(value, axis) {return value + ' degree';}
}

If you try to parse this JSON text, you will face an error because function(value, axis) {return value + ‘ degree’;} is not allowed here. Try to put this structure into this online JSON viewer to see that JSON format doesn’t accept functions. So, the idea is to pass the function as string:

{
    'borderWidth': '2px',
    'colors': ['#FFFFFF', 'CCCCCC'],
    'labelFormatter': 'function(value, axis) {return value + ' degree';}'
}

This syntax can be parsed. But we have another problem now. We have to make a real JavaScript function from its string representation. After trying a lot I found an easy solution. Normally, to parse a well-formed JSON string and return the resulting JavaScript object, you can use a native JSON.parse(…) method (implemented in JavaScript 1.7), JSON.parse(…) from json2.js written by Douglas Crockford or the jQuery’s $.parseJSON(…). The jQuery’s method only expects one parameter, the JSON text: $.parseJSON(jsonText). So, you can not modify any values with it. The first two mentioned methods have two parameters

JSON.parse(text, reviver)
 

The second parameter is optional, but exactly this parameter will help us! reviver is a function, prescribes how the value originally produced by parsing is transformed, before being returned. More precise: the reviver function can filter and transform the results. It receives each of the keys and values, and its return value is used instead of the original value. If it returns what it received, then the structure is not modified. If it returns undefined then the member is deleted. An example:

var transformed = JSON.parse('{'p': 5}', function(k, v) {if (k === '') return v; return v * 2;});

// The object transformed is {p: 10}

In our case, the trick is to use eval in the reviver to replace the string value by the corresponding function object:

var jsonText = '.....';  // got from any source

var jsonTransformed = JSON.parse(jsonText, function (key, value) {
    if (value && (typeof value === 'string') && value.indexOf('function') === 0) {
        // we can only pass a function as string in JSON ==> doing a real function
        eval('var jsFunc = ' + value);
        return jsFunc;
    }

    return value;
});

I know, eval is evil, but it doesn’t hurt here. Well, who doesn’t like eval there is another solution without it.

var jsonTransformed = JSON.parse(jsonText, function (key, value) {
    if (value && (typeof value === 'string') && value.indexOf('function') === 0) {
        // we can only pass a function as string in JSON ==> doing a real function
        var jsFunc = new Function('return ' + value)();
        return jsFunc;
    }

    return value;
});

Do you want to know how to develop your skillset to become a Web Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!

 

1. Building web apps with Node.js

2. HTML5 Programming Cookbook

3. CSS Programming Cookbook

4. AngularJS Programming Cookbook

5. jQuery Programming Cookbook

6. Bootstrap Programming Cookbook

 

and many more ....

 

 

One comment

  1. I think JSON format which you supply may be wrong. We should replace Apostroph character with quotes mark character.
    http://json.parser.online.fr/ – this page show error when I copy your JSON format to check.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

Want to take your WEB dev skills to the next level?

Grab our programming books for FREE!

Here are some of the eBooks you will get:

  • PHP Programming Cookbook
  • jQuery Programming Cookbook
  • Bootstrap Programming Cookbook
  • Building WEB Apps with Node.js
  • CSS Programming Cookbook
  • HTML5 Programming Cookbook
  • AngularJS Programming Cookbook