Prevent quoting specific values ​​with PHP json_encode ()

When using PHP json_encode to encode an array as a JSON string, is there any way to prevent the function from quoting certain values ​​in the returned string? The reason I'm asking is because I need javascript to interpret certain values ​​in an object as the names of real variables, like the name of an existing javascript function.

My ultimate goal is to use dedicated json as the configuration object for the ExtJS menu component, so the fact that everything is quoted does not allow me to successfully set properties such as the "handler" (click event handler function) of the children of the arrays.

+4
source share
7 answers

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

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

What we do (and what Zend_Json::encode() does) is to use a special marker class that encapsulates JavaScript expressions in a special class. The encoding then recursively passes through our encoded array, replacing all marker instances with some string. After using the built-in json_encode() we simply perform a line replacement to replace each special line with the __toString() value of the corresponding marker instance.

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

+3
source

The Bill function almost worked, it just needed the is_assoc () function.

But while I sorted it out, I cleaned it a bit. It seems to me that this works very well:

 <?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; } } 
+2
source

No, json_encode cannot do this. You need to construct your JS expression manually:

 $json = "{'special':" . json_encode($string) . " + js_var," . "'value': 123}"; 

(Try using json_encode for parts with a fixed value, as in the example above.)

+1
source

The json_encode function does not provide any functions for managing quotes. Quotation marks are also required for JavaScript to properly form the object from the JavaScript side.

To use the return value to build the object from the JavaScript side, use the json_encoded line to set flags in your association.

For instance:

 json_encode( array( "click_handler"=> "FOO" ) ); 

JavaScript side in AJAX:

 if( json.click_handler == "FOO" ) { json.click_handler = Your_Handler; } 

After these steps, you can transfer your object somewhere.

+1
source

my quickfix was as follows:

 $myobject->withquotes = 'mystring'; $myobject->withoutquotes = '##noquote## mystring ##noquote##'; 

and later

 str_replace(array('"##noquote## ', ' ##noquote##"'), '', json_encode($myobject)) 
Result

It looks something like this:

 {"withquotes":"mystring","withoutquotes":mystring} 
+1
source

Following the example of Stefan Gerig, I put this rude little class together. An example is below. You cannot use the serialize method if you used the label method, otherwise the markers will be stored in the final 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> 
0
source

Source: https://habr.com/ru/post/1343997/


All Articles