24 Aug 2012

PHP array integer keys, json_encode & JSON.parse vs. Browsers

While working on one site I found some differences between JavaScript's JSON.parse() function on different browsers. On server I used PHP's json_encode() function on Array and passed it to JavaScript. I needed to have this Array in JavaScript in exact order, but since keys in PHP Array were integers there was a problem, because different browsers ordered it differently (after JSON.parse()). Safari and Firefox kept exact order but Chrome and Opera changed it.

I needed, for example, something like this:



<?php
  $testArray = array();
  $testArray['5'] = 'first';
  $testArray['1'] = 'second';
  $testArray['2'] = 'third';
  $testArray['4'] = 'fourth';
  $testArray['3'] = 'fifth';
  $testJSON = json_encode( $testArray );
?>
<script type="text/javascript">
var test = <?php echo $testJSON; ?>;
var i;
for ( i in test ) {
  console.log( test[i] );
}
</script>

Safari & Firefox (as wanted)Chrome & Opera

	first
	second
	third
	fourth
	fifth

	second
	third
	fifth
	fourth
	first

I've tried many things to cast keys of Array to string. Like:



	$testArray = array();
	
	$testArray['1'] = 'first';
	$testArray[(string)2] = 'second';
	$a = '3';
	$testArray[ $a ] = 'third';
	$b = '4';
	$testArray[${'b'}] = 'fourth';
	$c = sprintf( '%s', 5 );
	$testArray[ $c ] = 'fifth';

Nothing of this worked. I've found rules of Array's key casting in PHP's Array reference. One of them says:
Strings containing valid integers will be cast to the integer type. E.g. the key "8" will actually be stored under 8. On the other hand "08" will not be cast, as it isn't a valid decimal integer. And this helped.


	$testArray = array();
	$testArray['05'] = 'first';
	$testArray['01'] = 'second';
	$testArray['02'] = 'third';
	$testArray['04'] = 'fourth';
	$testArray['03'] = 'fifth';

So the result is that I'm now using everywhere on this site keys starting with '0', and it is working so far. Anyone have some better solution to this?