PHP json_encode replacement

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