Вопрос о преобразовании объекта 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 
10
задан Lightness Races with Monica 17 June 2011 в 16:43
поделиться

4 ответа

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

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

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

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, определить правильное поведение в языке со слабой типизацией не так просто.

4
ответ дан 4 December 2019 в 02:25
поделиться

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

$arr = json_decode($json, true);

echo '<pre>';
print_r($arr);
echo '</pre>';
1
ответ дан 4 December 2019 в 02:25
поделиться
Array ( [0] => a ) a0:
Array ( [0] => b ) b0:b

Опять бесполезная атака PHP print_r !

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

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

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

1
ответ дан 4 December 2019 в 02:25
поделиться

Вы можете просто получить доступ к нему как к объекту (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

1
ответ дан 4 December 2019 в 02:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: