JSON对象转换问题

时间:2010-05-17 23:25:40

标签: php type-conversion 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 

5 个答案:

答案 0 :(得分:4)

this older question中有更多信息。简短版本是PHP对象/类上的properties遵循相同的naming convention as variables。数值属性在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的“错误”行为,但在弱键入的语言中定义正确的行为并不容易。

答案 1 :(得分:1)

您只能将其作为对象(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

答案 2 :(得分:1)

你为什么要这样做?你知道你可以直接将JSON解码值作为数组吗?

$arr = json_decode($json, true);

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

答案 3 :(得分:1)

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

PHP再次无益print_r次攻击!

第一个数组有一个整数键0,因为(array)强制转换试图将它变成一个类似平面列表的数组。

第二个数组保留你用它构造它的关联数组样式字符串键'0'

使用var_export代替print_r,您可以更轻松地看到差异。

答案 4 :(得分:1)

嗯,问题只存在于初始对象具有不允许的属性[也就是数字属性]时。这与json_encode / decode无关,而与涉及从对象转换为数组的任何操作无关。所有整数键都将无法访问。

http://www.php.net/manual/en/language.types.array.php - 指出:如果将对象转换为数组,则结果是一个数组,其元素是对象的属性。键是成员变量名,有一些值得注意的例外:整数属性是不可访问的;私有变量的类名前置于变量名;受保护的变量在变量名前面加上'*'。这些前置值在任一侧都有空字节。