Passing Functions Through JSON

Original author: Bas Wenneker
  • Transfer
From this topic you will learn how to send JavaScript functions via JSON using PHP (the concept itself can be applied to other languages).

PHP since version 5.2.0 includes the json_encode () and json_decode () functions. These functions encode data in JSON format and decode JSON into associative arrays. In json_encode (), a function cannot be encoded. In some cases, this is damn inconvenient.
  1. Added implementation example in Zend Framework.
  2. Question to karmavampires - do you know an option how to pass a handler to create an object differently?
  3. Commentary on why and who needs it.

Problem

// Возьмем произвольный массив
$foo = array(
    'number' => 1,
    'float'  => 1.5,
    'array'  => array(1,2),
    'string' => 'bar',
    'function'=> 'function(){return "foo bar";}'
);
// Теперь преобразуем массив в JSON
$json = json_encode($foo);
// Отдадим клиенту
echo $json;

* This source code was highlighted with Source Code Highlighter.

Result

{
    "number":1,
    "float":1.5,
    "array":[1,2],
    "string":"bar",
    "function":"function(){return \"foo bar\";}"
}
* This source code was highlighted with Source Code Highlighter.


Since if you do not enclose the definition of the function in quotation marks, that is, if you do not define it as a string, the code will not be executed. So basically jscon_encode () is not suitable for implementing this functionality.

Decision

  1. We pass through the array to be encoded.
  2. Check the encoded value for a function definition.
  3. We remember the value and replace it with a unique label.
  4. We encode the modified array using json_encode ().
  5. Replace the unique label with the original value.
  6. We give JSON to the client.
// Обрабатываемый массив.
$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){
 // Проверяем значения на наличие определения функции
 if(strpos($value, 'function(')===0){
    // Запоминаем значение для послудующей замены.
    $value_arr[] = $value;
    // Заменяем определение функции 'уникальной' меткой..
    $value = '%' . $key . '%';
    // Запоминаем метку для послудующей замены.
    $replace_keys[] = '"' . $value . '"';
 }
}

// Кодируем массив в JSON
$json = json_encode($foo);

// Полученный $json будет выглядеть так:
{
 "number":1,
 "float":1.5,
 "array":[1,2],
 "string":"bar",
 "function":"%function%"
}

// Заменяем метски оригинальными значениями.
$json = str_replace($replace_keys, $value_arr, $json);

// Отправляем клиенту.
echo $json;

// Клиент получит JSON такого вида:
{
 "number":1,
 "float":1.5,
 "array":[1,2],
 "string":"bar",
 "function":function(){return "foo bar";}
}

* This source code was highlighted with Source Code Highlighter.
Now in the received object, “function” is not a string, but a function. Actually the problem is solved. If you use this solution together with 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()); // => Отобразится alert 'foo bar'
  }
});

* This source code was highlighted with Source Code Highlighter.


Implementation in the Zend Framework:


$foo = array(
  'integer' =>9,
  'string'  =>'test string',
  'function' => Zend_Json_Expr(
    'function(){ window.alert("javascript function encoded by Zend_Json") }'
  ),
);

Zend_Json::encode($foo, false, array('enableJsonExprFinder' => true));
// it will returns json encoded string:
{
  "integer":9,
  "string":"test string",
  "function":function(){
    window.alert("javascript function encoded by Zend_Json")
  }
}

* This source code was highlighted with Source Code Highlighter.

Also popular now: