将stdClass转换为数组 - 键不可访问

时间:2016-08-18 15:41:40

标签: php json php-7 stdclass

当我做这样的事情时,我正在运行PHP7.0.9:

$s = json_decode('{"1": "xxx"}');//decode json to stdClass
$a = (array)$s;//cast to array
die(var_dump($a, $a['1'], $a[1], count($a)));

我得到了这个结果:

array (size=1)
  '1' => string 'xxx' (length=3) //<-- key 1 exists
null // $a['1'] yields null
null // $a[1] doesn't work either
int 1 // count shows there is 1 element in the array

我期待这个结果:

array (size=1)
  '1' => string 'xxx' (length=3)
string 'xxx' (length=3) // $a['1'] should work
null
int 1

我的问题:为什么我无法访问$a['1'],即使数组的countvar_dump告诉我此密钥存在?这是PHP中的错误还是某种功能?

1 个答案:

答案 0 :(得分:7)

引用PHP documentation

数组到对象

  

如果将对象转换为对象,则不会对其进行修改。如果将任何其他类型的值转换为对象,则会创建stdClass内置类的新实例。如果值为NULL,则新实例将为空。数组转换为具有按键和相应值命名的属性的对象,但除非迭代,否则将无法访问数字键。

Object to Array

在转换相反的方式时,类似的问题/怪癖也出现了:(documentation

  

如果将对象转换为数组,则结果是一个数组,其元素是对象的属性。键是成员变量名,有一些值得注意的例外:整数属性是不可访问的;私有变量的类名前置于变量名;受保护的变量在变量名前面加上'*'。这些前置值在任一侧都有空字节。这可能会导致一些意外行为:

基本上,具有数字属性的对象可以强制转换为数组,您可以迭代它,但是密钥是不可访问的(直接)。这是一个众所周知的怪癖。您可以使用json_decode($string, true);直接转换为数组,使用辅助循环“重建”数组来解决问题:

$reconstructed = [];
foreach ((array) $obj as $k => $v) {
    $reconstructed[$k] = $v;
}

这是一个错误还是一个功能尚不清楚。当我第一次遇到这种行为时,我把它称为bug。鉴于它的记录和已知的怪癖,我现在说它既不是。这不是一个真正的错误,因为它已知,被理解和记录,但它几乎不是功能。这只是大多数语言所具有的混乱怪癖之一。

你必须解决它,忍受它,避免它,并处理它。鉴于PHP邮件列表上有很多关于此问题的bug报告,并且它已添加到文档中,它可能很快就会被修复。