Bill Dami Bill Dami - 2 months ago 7
JSON Question

Prevent quoting of certain values with PHP json_encode()

When using PHP's json_encode to encode an array as a JSON string, is there any way at all to prevent the function from quoting specific values in the returned string? The reason I ask is because I need javascript to interpret certain values in the object as actual variable names, for example the name of an existing javascript function.

My end goal is to use the outputted json as the configuration object for an ExtJS Menu component, so the fact that everything gets quoted prevents me from successfully setting such properties as "handler" (click event handler function) of the child items arrays.

Answer

This is what I ended up doing, which is pretty close to what Stefan suggested above I think:

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;
    }
}