Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php JSON对象转换问题_Php_Type Conversion_Json - Fatal编程技术网

Php JSON对象转换问题

Php JSON对象转换问题,php,type-conversion,json,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>"); 我本以为第一行末尾是a0:a 编

我正在从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>");
我本以为第一行末尾是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>");

您可以将其作为对象(stdClass)而不是数组进行访问:

$json = '{"0" : "a"}';
$obj = json_decode($json);
print_r($obj);
echo("a0:".$obj->{"0"}."<br>");
第二个可选参数使其输出关联数组。
你为什么要这样做?您知道可以直接将JSON解码值作为数组吗

$arr = json_decode($json, true);

echo '<pre>';
print_r($arr);
echo '</pre>';
$arr=json\u decode($json,true);
回声';
印刷费($arr);
回声';

中有更多信息。简短的版本是在PHP对象/类上遵循相同的规则。数值属性在PHP对象上无效,因此,当从另一种具有数值键的语言(json/javascript)序列化对象时,没有明确的规则。虽然您似乎很清楚上述情况会发生什么,但有人持有不同的偏见,认为PHP在本例中的行为是完全有效和首选的

因此,这是一种缺陷,但更多的是规范中的一个未定义区域,没有明确的答案,所以不要期望行为改变以满足您的喜好,如果它确实改变了,也不要期望这种改变是永久的

为了解决评论中的一些问题,请考虑这个

array(1) {
  ["0"]=>
  string(1) "a"
}
array(1) {
  [0]=>
  string(1) "a"
}
array(1) {
  [0]=>
  string(1) "a"
}
这将输出类似这样的内容

Array ( [0] => a ) a0:
Array ( [0] => b ) b0:b
具有单个字符串键零的数组不是有效的PHP构造。如果您尝试创建一个PHP,它会将0转换为int。当您要求PHP执行一个没有定义的强制转换时,它最终会创建一个带有字符串键的数组(因为这里应该发生的事情的规则定义不正确)

虽然这显然是PHP的“错误”行为,但在弱类型语言中定义正确的行为并不容易

PHP的无用的
print\r
再次攻击

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

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


使用
var\u export
而不是
print\u r
,您可以更容易地看到差异。

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


-其中指出:如果将对象转换为数组,则结果是一个数组,其元素是对象的属性。键是成员变量名,但有几个显著的例外:整数属性不可访问;私有变量的类名在变量名前面;受保护变量的变量名前面有一个“*”。这些带前缀的值两边都有空字节。

这是难以置信的,但php就是这样做的。虫子:我很高兴你能确认这一行为。在使用了一段时间之后,我并不期望php是完美的。这不是它的主要优势。但也许我们能理解发生了什么。卡尔托瓦尔德酒店aka@karlthorwald:这很奇怪,我想这是某种错误。尝试通过PHP.net提交它。您错过了第三行,在那里对象被转换为数组。您的回答没有解释为什么我们可以在var_dump()中看到该项,但无法访问它。一般的问题是关于
object->array
转换,而不是关于如何使用
json\u decode
philfreo谢谢。这有助于我继续编码。但我现在会继续提问,也许有人会解释我发现的意外行为。OP karlthorwald-这并不能证明结果的合理性;-)是吗?但是,如果将
打印(
$a
转换为数组后,您仍然可以清楚地看到索引
0
没有被删除。是的。同意@Alix。对物体的解释。但由于我们显式地将对象强制转换为数组,所以我们希望它能够正常工作。即使新数组不包含那个“格式错误的键”,也可以解释它(因为对象的属性格式错误)。但半功能数组看起来有很多问题。更新了问题以解决其他评论。在$a的情况下,您将一个已经无效的对象转换为数组,因此您将进入未定义的行为区域,并且所有赌注都将取消。在$b的情况下,PHP会自动将“0”强制转换为int以生成有效数组。我同意这是一种奇怪的行为,但在任何语言中都会出现类似的奇怪行为,避免使用强类型。是的,上次使用
string vs integer
keys比较的更新澄清了这种php行为。谢谢。可能值得添加一个明显的修复:
json\u decode($json,true)
。知道打印效果不好会有很大帮助。仍然显示一个字符串键(参见问题中的扩展示例)@zerkms:,actually@user89021:Alan Storm的回答正确地指出了这个问题。作为对象存在的数据的中间步骤存在一个名为
0
的属性问题,该属性无效。
$arr = json_decode($json, true);

echo '<pre>';
print_r($arr);
echo '</pre>';
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"
}
Array ( [0] => a ) a0:
Array ( [0] => b ) b0:b