I ran into a problem with RiddleMeThis recently — the new online runtime needs to generate JavaScript structures on the server to hand over to the client. To do this I used the json_encode function, which requires PHP 5.2. Until now, RiddleMeThis hasn’t made many assumptions about the PHP runtime, but it turns out assuming PHP 5.2 is not a good idea. There’s a chunk of PHP you can get somewhere or other that will replace json_encode, but it’s annoyingly inconvenient.
Anyway, it turns out I wrote my own jsencode() function in order to deploy an earlier version of the runtime on a Mac OS X 10.5 server (which doesn’t have PHP 5.2, argh). This was a quick and dirty effort which served the purpose but is kind of evil (it wraps quotation marks around numbers, for one thing, and doesn’t quote the symbols — which is fine for JavaScript but not allowed for JSON, especially if you’re using a strict parser as found in jQuery 1.4.
Feel free to use either of these snippets as you please.
function jsencode( $obj ){ if( is_array( $obj ) ){ $code = array(); if( array_keys($obj) !== range(0, count($obj) - 1) ){ foreach( $obj as $key => $val ){ $code []= $key . ':' . jsencode( $val ); } $code = '{' . implode( ',', $code ) . '}'; } else { foreach( $obj as $val ){ $code []= jsencode( $val ); } $code = '[' . implode( ',', $code ) . ']'; } return $code; } else { return '"' . addslashes( $obj ) . '"'; } }
So, here’s a better version. It allows you to encode for JSON or (by default) JavaScript (useful for passing stuff from PHP server-side to JavaScript client-slide):
function jsencode( $obj, $json = false ){ switch( gettype( $obj ) ){ case 'array': case 'object': $code = array(); // is it anything other than a simple linear array if( array_keys($obj) !== range(0, count($obj) - 1) ){ foreach( $obj as $key => $val ){ $code []= $json ? '"' . $key . '":' . jsencode( $val ) : $key . ':' . jsencode( $val ); } $code = '{' . implode( ',', $code ) . '}'; } else { foreach( $obj as $val ){ $code []= jsencode( $val ); } $code = '[' . implode( ',', $code ) . ']'; } return $code; break; case 'boolean': return $obj ? 'true' : 'false' ; break; case 'integer': case 'double': return floatVal( $obj ); break; case 'NULL': case 'resource': case 'unknown': return 'null'; break; default: return '"' . addslashes( $obj ) . '"'; } }
To send the information from PHP to JavaScript, you’d write something like this:
<script type="text/javascript"> var foo = <?php echo jsencode( $some_variable ); ?>; </script>
To generate a JSON feed using this code you’d write something like this:
header('Cache-Control: no-cache, must-revalidate'); header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // some time in the past header('Content-type: application/json'); echo jsencode( $some_associative_array, true );