使用PHP json_encode()防止引用某些值

时间:2011-03-16 19:50:06

标签: php json

当使用PHP的json_encode将数组编码为JSON字符串时,是否有任何方法可以阻止函数在返回的字符串中引用特定值?我问的原因是因为我需要javascript来将对象中的某些值解释为实际的变量名,例如现有javascript函数的名称。

我的最终目标是使用输出的json作为ExtJS Menu组件的配置对象,因此引用所有内容的事实阻止我成功设置子项的“handler”(click事件处理函数)等属性阵列。

6 个答案:

答案 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>