Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent quoting of certain values with PHP json_encode()

Tags:

json

php

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.

like image 805
Bill Dami Avatar asked Mar 16 '11 19:03

Bill Dami


People also ask

What does the PHP function json_encode () do?

The json_encode() function is used to encode a value to JSON format.

What is json_encode and Json_decode in PHP?

JSON data structures are very similar to PHP arrays. PHP has built-in functions to encode and decode JSON data. These functions are json_encode() and json_decode() , respectively. Both functions only works with UTF-8 encoded string data.

What does json_encode return?

Syntax. The json_encode() function can return a string containing the JSON representation of supplied value. The encoding is affected by supplied options, and additionally, the encoding of float values depends on the value of serialize_precision.


2 Answers

What we do is (and that's what Zend_Json::encode() does too), is to use a special marker class that encapsulates Javascript expressions in a special class. The encoding then walks recursively through our array-to-be-encoded, replaces all marker instances with some string. After using the built-in json_encode() we simply do a string replace to replace each special string with the __toString() value of the respective marker instance.

You can either use Zend_Json directly (if that's possible) or check how they do it and adapt the code to your needs.

like image 170
Stefan Gehrig Avatar answered Sep 23 '22 01:09

Stefan Gehrig


Bill's function almost worked, it just needed the is_assoc() function added.

But while I was sorting this out, I cleaned it up a bit. This seems to work quite well for me:

<?php

/**
 * JSObject class.
 */

class JSObject {
    var $jsexp = 'JSEXP:';

    /**
     * is_assoc function.
     *
     * Determines whether or not the object is an associative array
     * 
     * @access public
     * @param mixed $arr
     * @return boolean
     */
    function is_assoc($arr) {
        return (is_array($arr) && count(array_filter(array_keys($arr),'is_string')) == count($arr));
    }

    /**
     * Encode object
     *
     * Encodes the object as a json string, parsing out items that were flagged as objects so that they are not wrapped in double quotes.
     *
     * @param     array   $properties
     * @return    string
     */
    function encode($properties = array()) {

        $is_assoc = $this->is_assoc($properties);

        $enc_left  = $is_assoc ? '{' : '[';
        $enc_right = $is_assoc ? '}' : ']';

        $outputArray = array();

        foreach ($properties as $prop => $value) {

            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))  : json_encode($value);
                }
                else {
                    $output .= json_encode($value);
                }


                $outputArray[] = $output;
            }
        }

        $fullOutput = implode(', ', $outputArray);

        return $enc_left . $fullOutput . $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;
    }
}
like image 24
Ben Hitchcock Avatar answered Sep 21 '22 01:09

Ben Hitchcock