2

I am trying to send a function in JSON response and tried to alert that function in js. Below is the code.

JS:

$('input').keyup(function(){
    $.ajax({
        type: "POST",
        url: "sample.php",
        dataType : 'json',
        data: 'val='+$('input').val(),
        success: function(response){

         var json = transport.responseText.evalJSON();
         alert(json.function()); // => **should alert 'foo bar' - but not**
        }
    });
});

PHP:

<?php
// Our sample array
$foo = array(
  'string'  => 'bar',
  'function'=> 'function(){return "foo bar";}'
);
$value_arr = array();
$replace_keys = array();
foreach($foo as $key => &$value){
  // Look for values starting with 'function('
  if(strpos($value, 'function(')===0){
    // Store function string.
    $value_arr[] = $value;
    // Replace function string in $foo with a 'unique' special key.
    $value = '%' . $key . '%';
    // Later on, we'll look for the value, and replace it.
    $replace_keys[] = '"' . $value . '"';
  }
}

// Now encode the array to json format
$json = json_encode($foo);

/* $json looks like:
{
  "number":1,
  "float":1.5,
  "array":[1,2],
  "string":"bar",
  "function":"%function%"
}
*/
// Replace the special keys with the original string.
$json = str_replace($replace_keys, $value_arr, $json);

// Send to to the client
echo $json;

/* This echoes the following string:
{
  "string":"bar",
  "function":function(){return "foo bar";}
}
*/
?>

what am I doing wrong in the above? Any help is appreciated.

karim79
  • 339,989
  • 67
  • 413
  • 406
asd
  • 101
  • 1
  • 1
  • 8

3 Answers3

5

JSON doesn't have any representation for functions. It's a data notation. Even if you trick PHP into sending a function (as you appear to be trying to do), a proper JSON deserializer on the client will throw an exception (ideally). Some very naive ones that rely on eval may pass the function through, but at that point, you're not using JSON, you're using JavaScript.

If you want to send back code, you need to send back JavaScript.

Separately, on this line:

alert(json.function());

...you have a syntax error. function is a reserved word in JavaScript. You can't use it as a property name literal. If you create a property with the name "function" (which you can, but probably shouldn't), to access it you have to use the string notation for accessing properties:

alert(json["function"]());

See also Gaby's answer, you seem to have mixed some Prototype code (evalJSON) into things.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
4

A function is not a valid data type in JSON. What you can do is to send a function expression as string:

{
  "string": "bar",
  "function":"function(){return \"foo bar\";}"
}

And then use eval:

var f = eval(response['function']);

But I would not recommend doing so. It is horrible, complex, not easy to understand or to maintain. It is basically the worst you can do.

What problem are you trying to solve with that?


If you have to send JavaScript from the server, then do so (don't return JSON), and use script as dataType.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • 1
    `eval` and Functions encoded as a string of code in json. That's horrible :( – Raynos Jun 02 '11 at 10:13
  • +1 *A value can be a string in double quotes, or a number, or true or false or null, or an object or an array. These structures can be nested.* http://json.org/ – karim79 Jun 02 '11 at 10:13
1

You are obviously using code from http://solutoire.com/2008/06/12/sending-javascript-functions-over-json/

But they are using prototype and not jQuery ..

The line transport.responseText.evalJSON(); means nothing in jQuery ..

Also have a look at http://json.org/ and you will see that functions is not supposed to go in JSON .. For more explanation read Is it valid to define functions in JSON results?

Community
  • 1
  • 1
Gabriele Petrioli
  • 191,379
  • 34
  • 261
  • 317