当使用PHP的json_encode将数组编码为JSON字符串时,是否有任何方法可以阻止函数在返回的字符串中引用特定值?我问的原因是因为我需要javascript来将对象中的某些值解释为实际的变量名,例如现有javascript函数的名称。
我的最终目标是使用输出的json作为ExtJS Menu组件的配置对象,因此引用所有内容的事实阻止我成功设置子项的“handler”(click事件处理函数)等属性阵列。
答案 0 :(得分:3)
我们所做的是(也是Zend_Json::encode()
所做的),是使用一个特殊的标记类,它将Javascript表达式封装在一个特殊的类中。然后编码以递归方式遍历我们要编码的数组,用一些字符串替换所有标记实例。使用内置json_encode()
后,我们只需执行字符串替换,将每个特殊字符串替换为相应标记实例的__toString()
值。
您可以直接使用Zend_Json
(如果可能)或查看how they do it并根据需要调整代码。
答案 1 :(得分:1)
不,json_encode无法做到这一点。您需要手动构建 JS表达式:
$json = "{'special':" . json_encode($string) . " + js_var,"
. "'value': 123}";
(尝试仍然使用json_encode作为固定值部分,如上例所示。)
答案 2 :(得分:1)
json_encode函数不提供任何控制引号的功能。引号也是JavaScript在JavaScript端正确形成对象所必需的。
为了使用返回的值在JavaScript端构造对象,请使用json_encoded字符串在关联中设置标志。
例如:
json_encode( array( "click_handler"=> "FOO" ) );
AJAX中的JavaScript方面:
if( json.click_handler == "FOO" ) {
json.click_handler = Your_Handler;
}
完成这些步骤后,您可以将对象传递到某处。
答案 3 :(得分:1)
我的quickfix是这样的:
$myobject->withquotes = 'mystring';
$myobject->withoutquotes = '##noquote## mystring ##noquote##';
以后
str_replace(array('"##noquote## ', ' ##noquote##"'), '', json_encode($myobject))
结果是这样的
{"withquotes":"mystring","withoutquotes":mystring}
答案 4 :(得分:0)
这就是我最终要做的事情,这与Stefan在上面提出的建议非常接近:
class JSObject
{
var $jsexp = 'JSEXP:';
/**
* Encode object
*
*
* @param array $properties
* @return string
*/
function encode($properties=array())
{
$output = '';
$enc_left = $this->is_assoc($properties) ? '{' : '[';
$enc_right = ($enc_left == '{') ? '}' : ']';
foreach($properties as $prop => $value)
{
//map 'true' and 'false' string values to their boolean equivalent
if($value === 'true') { $value = true; }
if($value === 'false') { $value = false; }
if((is_array($value) && !empty($value)) || (is_string($value) && strlen(trim(str_replace($this->jsexp, '', $value))) > 0) || is_int($value) || is_float($value) || is_bool($value))
{
$output .= (is_string($prop)) ? $prop.': ' : '';
if(is_array($value))
{
$output .= $this->encode($value);
}
else if(is_string($value))
{
$output .= (substr($value, 0, strlen($this->jsexp)) == $this->jsexp) ? substr($value, strlen($this->jsexp)) : '\''.$value.'\'';
}
else if(is_bool($value))
{
$output .= ($value ? 'true' : 'false');
}
else
{
$output .= $value;
}
$output .= ',';
}
}
$output = rtrim($output, ',');
return $enc_left.$output.$enc_right;
}
/**
* JS expression
*
* Prefixes a string with the JS expression flag
* Strings with this flag will not be quoted by encode() so they are evaluated as expressions
*
* @param string $str
* @return string
*/
function js($str)
{
return $this->jsexp.$str;
}
}
答案 5 :(得分:0)
在Stefan Gehrig的带领下,我将这个粗略的小课程放在了一起。以下示例。如果使用了mark方法,必须记住使用serialize方法,否则标记将保留在最终的json中。
class json_extended {
public static function mark_for_preservation($str) {
return 'OINK' . $str . 'OINK'; // now the oinks will be next to the double quotes
}
public static function serialize($stuff) {
$json = json_encode($stuff);
$json = str_replace(array('"OINK', 'OINK"'), '', $json);
return $json;
}
}
$js_arguments['submitHandler'] = json_extended::mark_for_preservation('handle_submit');
<script>
$("form").validate(<?=json_extended::serialize($js_arguments)?>);
// produces: $("form").validate({"submitHandler":handle_submit});
function handle_submit() {alert( 'Yay, pigs!'); }
</script>