Oki Erie Rinaldi
Oki Erie Rinaldi

Reputation: 1863

How to encode array to json containing function?

I have a little problem when I want to generate a json string containing javascript function.
I am using json_encode() function and it works well for encoding any object/array to be json string. But, I want to fill one of an element value by a javascript function.
json_encode() will always encode my function to string. How do I can remove the "(quote)? The quote" makes my function be a string. here's the example:

$var['status']     = "oke";
$var['fnFeedback'] = "function (a,b,c){ return a+c.FnSource; }";

echo json_encode($var);
//then the result
{[status:"oke"],[fnFeedback:"function (a,b,c){ return a+c.FnSource; }"]}
//value of fnFeedback of above json is a string

How can I make value of fnFeedback be a function?

Upvotes: 0

Views: 169

Answers (3)

Alnitak
Alnitak

Reputation: 339786

JSON cannot directly represent function bodies.

Given your JSON converted back into a JS object (below called myObj) one possibility is to convert the string directly into a function by wrapping it in parentheses (thus converting the function declaration into a function expression) and then passing it to eval:

var fnFeedback = eval('(' + myObj.fnFeedback + ')';

Please note that there are possible security issues with using eval - use with extreme caution and do not trust any function body supplied indirectly by third parties. It's safer to use Function instead, see Ted Hopp's later answer.

Upvotes: 1

Ted Hopp
Ted Hopp

Reputation: 234795

First, your sample isn't legal JSON syntax. Suppose it's something like this instead:

var input = '{"status":"oke","fnFeedback":"function (a,b,c){return a+c.FnSource;}"}';

One way to deal with this is to parse normally and then use eval to turn the value of the fnFeedback property into a Function object. However, using eval is usually a last resort (not to mention extremely risky if you aren't in total control of the value being eval-ed) and here there's a better approach using a little trick when parsing JSON data.

The trick is that JSON.parse accepts a second argument, which should be a function that accepts a key/value pair and returns the result. This will be called for every element that is parsed. Here's one that will turn your serialized function string into an actual function:

var result = JSON.parse(input,
    function(key, value) {
        // if value looks like a function definition, make a function
        if (value 
                && typeof value === "string" 
                && value.substr(0,8) == "function")
        {
            var startBody = value.indexOf('{') + 1;
            var endBody = value.lastIndexOf('}');
            var startArgs = value.indexOf('(') + 1;
            var endArgs = value.indexOf(')');

            return new Function(value.substring(startArgs, endArgs),
                                value.substring(startBody, endBody));
        }
        // else just return the value as is
        return value;
    });

When this is run, you can then see the results:

> result['fnFeedback']
[Function]
> result['fnFeedback'].toString()
'function anonymous(a,b,c) {\n return a+c.FnSource; \n}'

A more detailed explanation of how this works can be found here (from which the above was adapted). Also see this JavaScript gist for another (perhaps cleaner) sample code using the same idea (which I have not tested).

Upvotes: 2

KooiInc
KooiInc

Reputation: 122908

You can't. JSON means: JavaScript Object Notation. It is a serialisation to String values of all properties of an Object. Function properties are not serializable. If you deserialize the JSON-string to Object you'll have to convert the string containing the function to a real javascript function (e.g. using eval or new Function).

See also ..., chapter 5:

A JSON value can be an object, array, number, string, true, false, or null

Upvotes: 2

Related Questions