2016-04-06 24 views
4

早些时候,我有一些代码块,它工作正常,但在某些情况下,它扔PHP的通知:(阵列)型投来异样的行为对象数组转换

下面是代码:

$json = '{"1455260079":"Tracking : #34567808765098767 USPS","1455260723":"Delivered","1455261541":"Received Back"}'; 

$json_obj = json_decode($json); 
$json_array = (array) $json_obj; 
var_dump($json_array); 
print_r($json_array); 

echo $json_array["1455260079"]."\n"; 

输出:

array(3) { 
    ["1455260079"]=> 
    string(34) "Tracking : #34567808765098767 USPS" 
    ["1455260723"]=> 
    string(9) "Delivered" 
    ["1455261541"]=> 
    string(13) "Received Back" 
} 
Array 
(
    [1455260079] => Tracking : #34567808765098767 USPS 
    [1455260723] => Delivered 
    [1455261541] => Received Back 
) 

Notice: Undefined index: 1455260079 in /in/PULrp on line 14 

所以我上面的代码更改下面的代码和它的正常工作。

$json_array = json_decode($json, true); 
var_dump($json_array); 
print_r($json_array); 
echo $json_array["1455260079"]."\n"; 

输出:

array(3) { 
    [1455260079]=> 
    string(34) "Tracking : #34567808765098767 USPS" 
    [1455260723]=> 
    string(9) "Delivered" 
    [1455261541]=> 
    string(13) "Received Back" 
} 
Array 
(
    [1455260079] => Tracking : #34567808765098767 USPS 
    [1455260723] => Delivered 
    [1455261541] => Received Back 
) 
Tracking : #34567808765098767 USPS 

但在这里,我有点困惑,为什么(array)型铸造转换未在此代码工作。我知道json_decode($json, true)是将json字符串转换为数组的最佳选择,但$json_array = (array) $json_obj;也是一个有效的选项。

虽然调查这两个代码的var_dump它显示了一些差异,但两个数组的print_r完全相同。

我很想知道为什么var_dump这两种不同以及(array)类型铸造在第一种情况下如何将对象转换为数组?

我也注意到,如果我的情况下,键是数字,即1455260079,如果我将键1455260079更改为某个字符串,则按预期工作。

你可以看到完整的代码的输出:https://3v4l.org/PULrp

回答

3

几个发现我在这里:

引述:

  1. A numeric string as array key in PHP
  2. http://www.php.net/manual/en/language.types.array.php

他们声明:

包含有效整数的字符串将转换为整数类型。例如。键“8”实际上将被存储在8以下。另一方面,“08”不会被转换,因为它不是有效的十进制整数。

有趣的是(略有修改你的测试脚本):

<?php 
$json = '{"1455260079":"Tracking : #34567808765098767 USPS","1455260723":"Delivered","1455261541":"Received Back"}'; 

$json_obj = json_decode($json); 
$json_array = (array) $json_obj; 
var_dump($json_array); 
print_r($json_array); 

$newerArray = array(); 

echo "json_array contents: \n"; 
foreach($json_array as $k => $v){ 
    echo "k: $k " . gettype($k) . ", v: $v " . gettype($v) . "\n"; 
    $newerArray[$k] = $v; 
} 

echo "\n"; 

echo "newerArray contents: \n"; 
foreach($newerArray as $k => $v){ 
    echo "k: $k " . gettype($k) . ", v: $v " . gettype($v) . "\n"; 
} 

echo $json_array["1455260079"]."\n"; 
echo $newerArray["1455260079"]."\n"; 

输出是:

array(3) { 
    ["1455260079"]=> 
    string(34) "Tracking : #34567808765098767 USPS" 
    ["1455260723"]=> 
    string(9) "Delivered" 
    ["1455261541"]=> 
    string(13) "Received Back" 
} 
Array 
(
    [1455260079] => Tracking : #34567808765098767 USPS 
    [1455260723] => Delivered 
    [1455261541] => Received Back 
) 
json_array contents: 
k: 1455260079 string, v: Tracking : #34567808765098767 USPS string 
k: 1455260723 string, v: Delivered string 
k: 1455261541 string, v: Received Back string 

newerArray contents: 
k: 1455260079 integer, v: Tracking : #34567808765098767 USPS string 
k: 1455260723 integer, v: Delivered string 
k: 1455261541 integer, v: Received Back string 

Notice: Undefined offset: 1455260079 in /in/Eq1OI on line 24 

Tracking : #34567808765098767 USPS 

注意关键的两个数组类型 - 铸造阵列有(数字)string键,而重新分配的数组有integer键。

当您将对象转换为数组时,该键仍然是string。根据上面的报价,这不是数组的PHP定义所期望的。

因此,当您尝试使用“数字字符串”访问数组时,PHP仍然将string视为integer,但在内部,键仍然是字符串,导致未定义的数组。

这也意味着,对于关联数组,键比较是其实严格但实际上宽松

+0

所以基本上它不值得使用'(array)'类型转换,因为它会改变整个流的行为吗? –

+1

除非你的对象没有整数键,否则似乎应该避免使用''(array)'类型转换,正如@limekin的答案所指出的那样。 – kazenorin

2

原因在PHP手册中给出。

第一种情况(未定义索引错误):

$json_array = (array) $json_obj; 

鉴于Converting to array

如果对象被转换成一个阵列,其结果是一个数组,其 元素是对象的属性。这些密钥是成员变量 的名称,但有一些值得注意的例外:整数属性为 不可访问; ...

所以你应该使用json_decode($json_string, true)来获得一个关联数组。

第二种情况(带的print_r和的var_dump差异):

鉴于var_dump Description

该功能显示结构有关包括其类型和值的一个或多个 表达式的信息。数组和对象是 递归探索的值,缩进显示结构。

而在Return Values of print_r

如果给定的字符串,整型或浮点本身将被打印的值。 如果给定一个数组,值将以显示 键和元素的格式显示。类似的符号用于对象。

所以字符串将印有qoutes与var_dump并没有print_r qoutes。