views:

897

answers:

3

I can create a sparse php array (or map) using the command:

$myarray = array(10=>'hi','test20'=>'howdy');

I want to serialize/deserialize this as JSON. I can serialize it using the command:

$json = json_encode($myarray);

which results in the string {"10":"hi","test20":"howdy"}. However, when I deserialize this and cast it to an array using the command:

$mynewarray = (array)json_decode($json);

I seem to lose any mappings with keys which were not valid php identifiers. That is, mynewarray has mapping 'test20'=>'howdy', but not 10=>'hi' nor '10'=>'hi'.

Is there a way to preserve the numerical keys in a php map when converting to and back from json using the standard json_encode / json_decode functions?

(I am using PHP Version 5.2.10-2ubuntu6.4.)

+9  A: 

json_decode returns an object of type stdClass by default. You access members as properties (i.e., $result->test20). 10 isn't a valid name for a property, which is why you're losing it.

Instead of casting to an array, you can pass true as a second argument to json_decode to make it return an associative array itself:

$mynewarray = json_decode($json, true);

If you do that, $mynewarray[10] will work fine.

Chris Smith
Thanks Chris, this is exactly what I needed.
Isaac Sutherland
A: 

What version of PHP? On 5.2 the following program/script

$myarray = array(10=>'hi','test20'=>'howdy');
$json = json_encode($myarray);
$mynewarray = (array) json_decode($json);
var_dump($mynewarray);

Outputs

array(2) {
  ["10"]=>
  string(2) "hi"
  ["test20"]=>
  string(5) "howdy"
}

Which doesn't display the behavior you're describing.

That said, if your version of PHP is miscasting the JSON, try using get_object_vars on the stdClass object that json_decode returns

get_object_vars(json_decode($json))

That might return better results.

Alan Storm
it has "10" index which can't be accessed through `[]` operator in PHP
vava
Ah, got it, it serialize the key as a string that happens to be a number, which you can't get at. The get_object_vars solution should solves that, as well as the second parameter of json_decode, mentioned above.
Alan Storm
A: 

The problem is in the conversion from object to array.

$a = (array)json_decode('{"10":"hi","test20":"howdy"}');
var_dump($a);

//outputs
array(2) {
  ["10"]=>
     string(2) "hi"
  ["test20"]=>
     string(5) "howdy"
}

See how this array have index "10"? But in PHP, everything that looks like a number gets converted into a number, especially in array indexes. You can't just get a["10"] because it converts "10" into a number and this array does not have such an index.

However, foreach works.

foreach ($a as $key => $value) {
   var_dump($key);
   var_dump($value);
}

//outputs
string(2) "10"
string(2) "hi"
string(6) "test20"
string(5) "howdy"

You can also treat result of json_decode as an object. While you won't be able to do $a->10 or $a->"10",

$a = json_decode('{"10":"hi","test20":"howdy"}');
$b = 10;
var_dump($a->$b);

//outputs
string(2) "hi"

works.

But most likely, as Chris said, you just want to pass true as a second argument.

$a = json_decode('{"10":"hi","test20":"howdy"}', true);
var_dump($a[10]);

//outputs
string(2) "hi"
vava