【问题标题】:JSON object conversion questionJSON对象转换问题
【发布时间】:2011-02-20 16:06:07
【问题描述】:

我正在从 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 

【问题讨论】:

  • 难以置信,但这就是 php 所做的 %) 一个错误?
  • zerkms:我很高兴你能确认这种行为。使用了一段时间后,我不希望 php 完美。这不是它的主要优势。但也许我们可以理解发生了什么。 OP karlthorwald - 又名
  • @karlthorwald:这很奇怪,我认为这是某种错误。尝试通过 PHP.net 提交。

标签: php type-conversion json


【解决方案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

【讨论】:

  • 您错过了第三行,其中对象被转换为数组。您的回答没有解释为什么我们可以在 var_dump() 中看到该项目但无法访问它。一般问题是关于object-&gt;array 转换,而不是关于如何使用json_decode
  • philfreo 谢谢。这有助于我继续编码。但我现在很好地保持问题开放,也许有人解释了我发现的意外行为。 OP karlthorwald - 又名
【解决方案2】:

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

$arr = json_decode($json, true);

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

【讨论】:

  • 这并不能证明结果是合理的 ;-) 是吗?
【解决方案3】:

this older question 中有更多信息。简短的版本是 PHP 对象/类上的 properties 遵循相同的 naming convention as variables。 PHP 对象上的数字属性无效,因此对于从具有数字键的另一种语言(json/javascript)序列化对象时应该发生什么没有明确的规则。虽然对您来说上面应该发生什么似乎很明显,但有不同偏见的人认为 PHP 在这种情况下的行为是完全有效和首选的。

所以,这是一个错误,但更多的是规范中未定义的区域,没有明确的答案,所以不要指望行为会改变以满足您的喜好,如果它确实发生了变化,也不要指望这种变化成为永久的。

要解决 cmets 中的一些问题,请考虑这一点

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 的“错误”行为,但在弱类型语言中定义正确的行为并不容易。

【讨论】:

  • 不过,如果print_r() $a 被转换为数组后,您可以清楚地看到索引0 没有被删除。
  • 是的。同意@Alix。 stackoverflow.com/questions/1869812/… 中的解释适用于对象。但是由于我们明确地将对象转换为数组,我们希望它能够以常规方式工作。即使新数组不包含那个“格式错误的键” - 它也可以解释(因为对象的格式错误)。但是半功能数组看起来很麻烦。
  • 更新了问题以解决其他 cmets。在 $a 的情况下,您将 一个已经无效的对象 转换为一个数组,因此您进入了未定义的行为领域并且所有的赌注都关闭了。在 $b 的情况下,PHP 自动将“0”转换为 int 以生成有效数组。我同意这是一种奇怪的行为,但是在任何避免强类型输入的语言中,你最终都会出现类似的奇怪行为。
  • 是的,与string vs integer 键比较的最后更新澄清了这种 php 行为。谢谢。
  • 可能值得添加明显的修复:json_decode($json, true)
【解决方案4】:
Array ( [0] => a ) a0:
Array ( [0] => b ) b0:b

PHP 无用的print_r 再次攻击!

第一个数组有一个整数键0,因为(array) 演员试图将它变成一个扁平的类似列表的数组。

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

使用var_export 而不是print_r,您可以更轻松地看到差异。

【讨论】:

  • 知道 print_r 不能正常工作很有帮助。仍然 var_export 显示一个字符串键(请参阅问题中的扩展示例)
  • @zerkms: var_export,实际上
  • @user89021:Alan Storm 的回答正确识别了问题。作为对象存在的数据的中间步骤存在名为0 的属性的问题,这是无效的。
【解决方案5】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-18
    • 1970-01-01
    • 1970-01-01
    • 2015-09-15
    • 1970-01-01
    • 2016-09-12
    • 1970-01-01
    相关资源
    最近更新 更多