Вопрос об объекте объекта JSON

Я перехожу от JSON к объекту и от объекта к массиву. Это не то, что я ожидал, можете ли вы мне объяснить?

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

Выходной сигнал здесь:

Array ( [0] => a ) a0:
Array ( [0] => b ) b0:b

Я ожидал бы a0: a в конце первой строки.

Изменить: после прочтения ответов я расширил код, что делает поведение более ясным:

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

Вывод расширенного примера:

array ( '0' => 'a', )a0:
a
array ( 'x' => 'b', )bx:b
array ( 1 => 'c', )c1:c
array ( 0 => 'd', )d0:d 

Ответ 1

Более подробная информация в этом старом вопросе. Краткая версия состоит в том, что properties на объектах/классах PHP следуют тем же соглашение об именах в качестве переменных. Числовое свойство недопустимо для объекта PHP, поэтому нет четкого правила относительно того, что должно произойти при сериализации объекта с другого языка (json/javascript), который имеет числовой ключ. Хотя вам кажется очевидным, что должно произойти с вышесказанным, кто-то с другим уклоном видит, что поведение PHP в этом случае является совершенно правильным и предпочтительным.

Итак, это своего рода ошибка, но больше области undefined спецификации без четкого ответа, поэтому не ожидайте, что поведение изменится в соответствии с вашими предпочтениями, и если это произойдет, не ожидайте которые изменяются как постоянные.

Чтобы устранить некоторые из проблем в комментариях, рассмотрите этот

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

который выведет что-то вроде этого

array(1) {
  ["0"]=>
  string(1) "a"
}
array(1) {
  [0]=>
  string(1) "a"
}
array(1) {
  [0]=>
  string(1) "a"
}

Массив с нулевым нулевым ключом не является корректной конструкцией PHP. Если вы попытаетесь создать один PHP, он превратит нуль в int для вас. Когда вы попросите PHP сделать бросок, для которого нет определения, он заканчивает создание массива с помощью строкового ключа (из-за плохо определенных правил вокруг того, что должно произойти здесь).

Хотя наглядно очевидно, что это "неправильное" поведение со стороны PHP, определение правильного поведения на языке, который слабо набрал, непросто.

Ответ 2

Вы можете просто получить доступ к нему как к объекту (stdClass), а не к массиву:

$json = '{"0" : "a"}';
$obj = json_decode($json);
print_r($obj);
echo("a0:".$obj->{"0"}."<br>");

Это наиболее прямолинейно, поскольку ваш JavaScript был объектом ({}), а не массивом [] для начала.

В качестве альтернативы вы можете сделать это

$arr = json_decode($json, true);

Второй необязательный параметр выводит ассоциативный массив. http://us.php.net/json_decode

Ответ 3

Зачем ты это делаешь? Вы знаете, что вы можете иметь JSON-декодированные значения в виде массива напрямую?

$arr = json_decode($json, true);

echo '<pre>';
print_r($arr);
echo '</pre>';

Ответ 4

Array ( [0] => a ) a0:
Array ( [0] => b ) b0:b

PHP бесполезные атаки print_r снова!

Первый массив имеет целочисленный ключ 0, потому что приведение (array) пытается превратить его в плоский список-подобный массив.

Во втором массиве сохраняется строковый ключ '0' с ассоциативным массивом. Вы построили его с помощью.

Используйте var_export вместо print_r, и вы можете легко увидеть разницу.

Ответ 5

Ну, проблема существует только тогда, когда исходный объект имеет свойства, которые не разрешены [акамерные числа]. Это не связано с json_encode/decode, но с любой операцией, включающей преобразование из объектов в массив. Все целые ключи будут недоступны.

http://www.php.net/manual/en/language.types.array.php - где указано, что: если объект преобразуется в массив, результатом является массив, элементами которого являются свойства объекта. Ключи - это имена переменных-членов, с несколькими заметными исключениями: целочисленные свойства недоступны; частные переменные имеют имя класса, добавленное к имени переменной; защищенные переменные имеют "*", добавленные к имени переменной. Эти предварительные значения имеют нулевые байты с обеих сторон.