Evite la cita de ciertos valores con PHP json_encode ()

Cuando se utiliza json_encode de PHP para codificar una matriz como una cadena JSON, ¿hay alguna manera de evitar que la función cotice valores específicos en la cadena devuelta? La razón por la que pregunto es porque necesito JavaScript para interpretar ciertos valores en el objeto como nombres de variables reales, por ejemplo, el nombre de una función de JavaScript existente.

Mi objective final es utilizar el json generado como el objeto de configuración para un componente de menú ExtJS, por lo que el hecho de que todo se cita no me permite configurar correctamente las propiedades como “controlador” (haga clic en función del controlador de eventos) de las matrices de elementos secundarios.

Lo que hacemos es (y eso es lo que Zend_Json::encode() también hace), es usar una clase de marcador especial que encapsula expresiones de Javascript en una clase especial. La encoding luego camina recursivamente a través de nuestra matriz por codificar, reemplaza todas las instancias de marcador con alguna cadena. Después de usar el json_encode() simplemente hacemos un reemplazo de cadena para reemplazar cada cadena especial con el valor __toString() de la instancia del marcador respectivo.

Puede usar Zend_Json directamente (si es posible) o verificar cómo lo hacen y adaptar el código a sus necesidades.

La función de Bill casi funcionó, solo necesitaba la función is_assoc () añadida.

Pero mientras estaba resolviendo esto, lo limpié un poco. Esto parece funcionar bastante bien para mí:

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

No, json_encode no puede hacer eso. Necesitas construir tu expresión JS a mano entonces:

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

(Trate de seguir usando json_encode para partes de valor fijo, como en el ejemplo anterior).

La función json_encode no proporciona ninguna funcionalidad para controlar las comillas. Las comillas también son necesarias para que JavaScript forme correctamente el objeto en el lado de JavaScript.

Para usar el valor devuelto para construir un objeto en el lado de JavaScript, use la cadena json_encoded para establecer indicadores en su asociación.

Por ejemplo:

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

Lado JavaScript en el AJAX:

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

Después de estos pasos, puedes pasar tu objeto a alguna parte.

mi quickfix fue esto:

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

y después

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

resultado es algo como esto

 {"withquotes":"mystring","withoutquotes":mystring} 

Esto es lo que terminé haciendo, que es bastante parecido a lo que Stefan sugirió anteriormente, creo:

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

Siguiendo el ejemplo de Stefan Gehrig, reuní esta pequeña y áspera clase. Ejemplo a continuación. Uno debe recordar usar el método de serializar si se ha usado el método de marca, de lo contrario los marcadores persistirán en el json final.

 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');