I ran into an odd PHP thing (bug?) today. I had an object that had been extracted from a string using json_decode. After type-casting it to an array, any entries stored with numeric keys were inaccessible when calling by key, though iteration worked fine.

Here’s a simplified example:

// make an associative array
$myList = array(
	2=>'two',
	4=>'four',
	6=>'six',
	8=>'eight',
	'nine'=>'nine'
);
// json encode to string
$myList = json_encode($myList);
// json decode to object
$myList = json_decode($myList);
// typecast back to array
$myList = (array) $myList;
// test output
$test1 = (array_key_exists(4, $myList))
	? $myList[4] : 'nothing!';
$test2 = (array_key_exists('nine', $myList))
	? $myList['nine'] : 'nothing!';
echo 'test1: '.$test1.', test2: '.$test2;


I’d expect the output to be:

test1: four, test2: nine

…but alas, it is:

test1: nothing!, test2: nine

String values seem to be unaffected, since the second test variable works just fine. Oddly, I can fetch the array keys manually, and all seems well:

$myKeys = array_keys($myList);
$test3 = (in_array(4, $myKeys)) ? 'found key!' : 'nothing!';

…but it still can’t be accessed by key as $myList[4]. I know PHP does some odd things with array keys by trying to convert strings of numeric values to numbers. Maybe that’s what is happening – the conversion to integer is not happening via json_decode, but the rest of PHP expects that it has, so can’t access a string key of a numeric value? But just guessing.

The obvious work-around is to use the 2nd parameter in json_decode to convert the string directly to an array, which works fine:

$myList = json_encode($myList);
$myList = json_decode($myList, true);

Or, if you can’t easily control the json_decode part, you can repair the array manually by creating a new array, iterating through the old one, and rebuilding it normally:

function fixBustedArray($array)
{
	$results = array();
	foreach ($array as $key=>$val) $results[$key] = $val;
	return $results;
}

Does anybody know if this is a bug, or expected behavior that I’m not understanding?