将多维对象转换为数组

28
我正在使用亚马逊产品广告API。返回的值是多维对象。
它长这样:
object(AmazonProduct_Result)#222 (5) {
  ["_code":protected]=>
  int(200)
  ["_data":protected]=>
  string(16538) 
array(2) {
    ["IsValid"]=>
    string(4) "True"
    ["Items"]=>
    array(1) {
      [0]=>
      object(AmazonProduct_Item)#19 (1) {
        ["_values":protected]=>
        array(11) {
          ["ASIN"]=>
          string(10) "B005HNF01O"
          ["ParentASIN"]=>
          string(10) "B008RKEIZ8"
          ["DetailPageURL"]=>
          string(120) "http://www.amazon.com/Case-Logic-TBC-302-FFP-Compact/dp/B005HNF01O?SubscriptionId=AKIAJNFRQCIJLTY6LDTA&tag=*********-20"
          ["ItemLinks"]=>
          array(7) {
            [0]=>
            object(AmazonProduct_ItemLink)#18 (1) {
              ["_values":protected]=>
              array(2) {
                ["Description"]=>
                string(17) "Technical Details"
                ["URL"]=>
                string(217) "http://www.amazon.com/Case-Logic-TBC-302-FFP-Compact/dp/tech-data/B005HNF01O%3FSubscriptionId%3DAKIAJNFRQCIJLTY6LDTA%26tag%*******-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3DB005HNF01O"
              }
            }
            [1]=>
            object(AmazonProduct_ItemLink)#17 (1) {
              ["_values":protected]=>
              array(2) {

我的意思是,它还包含对象内的数组。我希望将它们全部转换为多维数组。


1
为什么你需要这个变量成为一个数组?许多常见的数组操作(如foreach)也可以用于对象。 - MrGlass
如何检查对象中是否存在某个值?我尝试使用isset但它不起作用。 - Giri
由于它是一个对象,它的值应该始终存在。您应该检查它是否设置为可用的内容(或者只是 null)。 - MrGlass
谢谢MrGlass。当我使用is_null函数时,它有效。谢谢。 - Giri
6个回答

148

我知道这篇文章有点老,但你可以尝试下面的代码:

$array = json_decode(json_encode($object), true);

其中 $object 是 API 的响应。


1
注意:使用此方法可能会丢失在soapClient响应中使用的二进制值,例如PDF或类似文件。 - celsowm
虽然这个解决方案很有效,但我真的很想知道为什么没有原生的PHP方法来实现这个... 这个答案已经有10年了,我仍然找不到比这更好的方法。难道没有现代化的方式吗?即使它在后台做的是同样的事情,但它只是在代码中混淆了它的功能... - undefined
或者等一下... get_object_vars($object) 是等价的吗?请参考 Quolonel Questions 的回答。 - undefined

24
您可以使用如下递归函数:
function object_to_array($obj, &$arr)
{
 if (!is_object($obj) && !is_array($obj))
 {
  $arr = $obj;
  return $arr;
 }

 foreach ($obj as $key => $value)
 {
  if (!empty($value))
  {
   $arr[$key] = array();
   objToArray($value, $arr[$key]);
  }
  else {$arr[$key] = $value;}
 }

 return $arr;
}

您可能需要将其变得更整洁。 - SubRed
6
为了实现这个常见的请求,可以使用稍微更整洁的方法:函数 objectToArray($data) { 如果 $data 是对象,则将其转换为关联数组。如果 $data 是数组,则对数组中的每个元素递归调用此函数,然后返回结果。} - Kevin Op den Kamp
你好 @SubRed,你的回答对我很有帮助!我的问题是在 &$arr 中我们需要传递什么? - SagarPPanchal
1
嗨@SagarPanchal,变量&$arr是您的结果变量。您可以像这样使用它https://gist.github.com/anonymous/346f780acda292dea4cd。希望能帮到您。 - SubRed

5
function convertObjectToArray($data) {
    if (is_object($data)) {
        $data = get_object_vars($data);
    }

    if (is_array($data)) {
        return array_map(__FUNCTION__, $data);
    }

    return $data;
}

感谢Kevin Op den Kamp的贡献。


1

我写了一个函数来完成这个任务,并且还将所有的json字符串转换为数组。对我来说,这很有效。

function is_json($string) {
    // php 5.3 or newer needed;
    json_decode($string);
    return (json_last_error() == JSON_ERROR_NONE);
}

function objectToArray($objectOrArray) {
    // if is_json -> decode :
    if (is_string($objectOrArray)  &&  is_json($objectOrArray)) $objectOrArray = json_decode($objectOrArray);

    // if object -> convert to array :
    if (is_object($objectOrArray)) $objectOrArray = (array) $objectOrArray;

    // if not array -> just return it (probably string or number) :
    if (!is_array($objectOrArray)) return $objectOrArray;

    // if empty array -> return [] :
    if (count($objectOrArray) == 0) return [];

    // repeat tasks for each item :
    $output = [];
    foreach ($objectOrArray as $key => $o_a) {
        $output[$key] = objectToArray($o_a);
    }
    return $output;
}

1

如果你像我一样来到这里,却没有找到适合你情况的正确答案,那么这个修改过的之前回答中的版本最终对我起了作用:

protected function objToArray($obj)
{
    // Not an object or array
    if (!is_object($obj) && !is_array($obj)) {
        return $obj;
    }

    // Parse array
    foreach ($obj as $key => $value) {
        $arr[$key] = $this->objToArray($value);
    }

    // Return parsed array
    return $arr;
}

原始值是一个JSON字符串。方法调用看起来像这样:

$array = $this->objToArray(json_decode($json, true));

1

这是一个老问题,但最近我遇到了这个问题并想出了自己的解决方案。

array_walk_recursive($array, function(&$item){
    if(is_object($item)) $item = (array)$item;
});

现在,如果$array本身就是一个对象,您可以在将其放入array_walk_recursive之前将其转换为数组:
$array = (array)$object;
array_walk_recursive($array, function(&$item){
    if(is_object($item)) $item = (array)$item;
});

还有一个小例子:

array_walk_recursive($array,function(&$item){if(is_object($item))$item=(array)$item;});

在我的情况下,我有一个来自第三方来源的stdClass对象数组,其中有一个字段/属性的值我需要用作参考以找到其包含的stdClass,以便我可以访问该元素中的其他数据。基本上是比较两个数据集中的嵌套键。由于我需要多次执行此操作,因此我不想为每个要查找的项遍历它。解决这个问题的方法通常是使用array_column,但它不适用于对象。所以我首先做了上面的操作。

不知道为什么,尽管看起来应该可以工作,但这段代码在我试图转换的数组上没有起作用。一直没能弄清楚原因。以下是代码示例:https://3v4l.org/YRFLq - Cave Johnson
减少了一些问题:https://3v4l.org/Vn6aH。看起来具有对象属性的对象不起作用? - Cave Johnson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接