JSON object conversion question
I am converting from JSON to object and from object to array. It does not what I expected, can you explain to me?
$json = '{"0" : "a"}';
$obj = json_decode($json);
$a = (array) $obj;
print_r($a);
echo("a0:".$a开发者_如何学运维["0"]."<br>");
$b = array("0" => "b");
print_r($b);
echo("b0:".$b["0"]."<br>");
The output here is:
Array ( [0] => a ) a0:
Array ( [0] => b ) b0:b
I would have expected a0:a at the end of the first line.
Edit: After reading the answers I extended the code, which makes the behaviour more clear:
//extended example
$json = '{"0" : "a"}';
$obj = json_decode($json);
$a = (array) $obj;
var_export($a);
echo("a0:".$a["0"]."<br>"); //this line does not work, see the answers
echo $obj->{"0"}."<br>"; //works!
$json = '{"x" : "b"}';
$obj = json_decode($json);
$b = (array) $obj;
var_export($b);
echo("bx:".$b["x"]."<br>");
$c = array("1" => "c");
var_export($c);
echo("c1:".$c["1"]."<br>");
$d = array("0" => "d");
var_export($d);
echo("d0:".$d["0"]."<br>");
Output of extended example:
array ( '0' => 'a', )a0:
a
array ( 'x' => 'b', )bx:b
array ( 1 => 'c', )c1:c
array ( 0 => 'd', )d0:d
There's more information in this older question. The short version is that properties on PHP objects/classes follow the same naming convention as variables. A numerical property is invalid on a PHP object, so there's no clear rule as to what should happen when serializing an object from another language (json/javascript) that has a numerical key. While it seems obvious to you what should happen with the above, someone with a different bias sees PHP's behavior in this instance as perfectly valid and preferred.
So, it's kind of a bug, but more an undefined area of the spec with no clear answer, so don't expect the behavior to change to meet your liking, and if it does change, don't expect that change to be permanent.
To address some of the issues in the comments, consider this
header('Content-Type: text/plain');
$json = '{"0" : "a"}';
$obj = json_decode($json);
$a = (array) $obj;
var_dump($a);
var_dump(array(0=>'a'));
var_dump(array('0'=>'a'));
that will output something like this
array(1) {
["0"]=>
string(1) "a"
}
array(1) {
[0]=>
string(1) "a"
}
array(1) {
[0]=>
string(1) "a"
}
An array with a single string key zero isn't a valid PHP construct. If you try to create one PHP will turn the zero into an int for you. When you ask PHP to do a cast it doesn't have a definition for, it ends up creating an array with a string key (because of the ill defined rules around what should happen here).
While it's blatantly obvious that this is "wrong" behavior on the part of PHP, defining the right behavior in a language that's weakly typed isn't easy.
You can just access it as an object (stdClass) rather than an array:
$json = '{"0" : "a"}';
$obj = json_decode($json);
print_r($obj);
echo("a0:".$obj->{"0"}."<br>");
This is the most straightforward since your JavaScript was an object ({}
) rather than an array []
to begin with.
Alternatively, you can do this
$arr = json_decode($json, true);
The second optional parameter makes it output an associative array. http://us.php.net/json_decode
Why are you doing this? Do you know you can have the JSON decoded values as an array directly?
$arr = json_decode($json, true);
echo '<pre>';
print_r($arr);
echo '</pre>';
Array ( [0] => a ) a0:
Array ( [0] => b ) b0:b
PHP's unhelpful print_r
attacks again!
The first array has an integer key 0
, because the (array)
cast tries to turn it into a flat list-like array.
The second array retains the associative-array-style string key '0'
you constructed it with.
Use var_export
instead of print_r
and you can see the difference more easily.
Well, the problem only exists when the initial object has properties that are not allowed [aka properties that are numerical]. This is not related to json_encode/decode, but to any operation involving converting from objects into array. All the integer keys will be rendered inaccessible.
http://www.php.net/manual/en/language.types.array.php - where it is pointed that : If an object is converted to an array, the result is an array whose elements are the object's properties. The keys are the member variable names, with a few notable exceptions: integer properties are unaccessible; private variables have the class name prepended to the variable name; protected variables have a '*' prepended to the variable name. These prepended values have null bytes on either side.
精彩评论