In this post I’ll present a way to send javascript functions over JSON from a php server (but it should work on other platforms too). Since PHP version 5.20 PHP includes the functionsjson_encode() and json_decode(). These functions encode values into JSON formatting and decode JSON formatted strings into associative arrays. The json_encode() function is not able to encode a value into a (javascript) function. This is a common issue when configuring graphs from Flotr (my Javascript plotting library) with JSON data. Here are my findings.
The Problem: Server-side
To get a better feeling for the problem, I’ll show you what happens when we pass an array to json_encode:
// Our sample array
$foo = array(
'number' => 1,
'float' => 1.5,
'array' => array(1,2),
'string' => 'bar',
'function'=> 'function(){return "foo bar";}'
);
// Now encode the array to JSON format
$json = json_encode($foo);
// Send to to the client
echo $json;
...
// This sends the following string to the client:
{
"number":1,
"float":1.5,
"array":[1,2],
"string":"bar",
"function":"function(){return \"foo bar\";}"
}
The solution
My solution is very simple:
- Loop over the associative array that is about to be encoded
- Look for values that start with a function definition (like ‘function(‘)
- Remember the value and replace it with a unique key (within the assoc array)
- Encode the changed assoc array to JSON using
json_encode() - Replace the unique keys enclosed in quotation marks with their original values
- Echo the json string
In PHP:
// Our sample array
$foo = array(
'number' => 1,
'float' => 1.5,
'array' => array(1,2),
'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:
{
"number":1,
"float":1.5,
"array":[1,2],
"string":"bar",
"function":function(){return "foo bar";}
}
Now the ‘function’ key is not a String anymore, but it’s a function. So our problem is solved. When using Prototype, it will look something like this:
new Ajax.Request('json_server.php', {
method:'get',
onSuccess: function(transport){
var json = transport.responseText.evalJSON();
alert(json.function()); // => alerts 'foo bar'
}
});
There might be dozens of solutions to the problem stated above, but I couldn’t find ’em on the net. If you know a better technique, please share it!
Source: http://solutoire.com/2008/06/12/sending-javascript-functions-over-json/