将 PHP stdClass object 展平为数组,保持数组维度

Flatten PHP stdClass object to array maintaining array dimensions

我正在处理包含嵌套包装器且其 child(ren) 具有嵌套属性的 soap 响应。

我正在尝试将这些回复扁平化为:

  1. 删除包装纸
  2. 平child仁
  3. 保持个体children(维度)

我目前正在使用以下实现#1 和#3 的方法,但它不会压平内部 children。请注意,$this->response 在展平之前从 stdClass 转换为 Array。

我怎样才能同时压平内部嵌套的 child 元素?

private function toArray()
{
    $this->response = json_decode(json_encode($this->response), true);
    return $this;
}

private function flatten($array = null)
{
    if (is_null($array)) {
        $array = $this->response;
    }
    if (is_array($array)) {
        foreach ($array as $k => $v) {
            if (count($v) == 1 && is_array($v)) {
                return $this->flatten($v);
            }
            if (isset($v[0])) {
                $this->response = $v;
                return $this;
            }
            unset($this->response);
            $this->response[] = $v;
            return $this;
        }
    }
}

...这将改变这个:

stdClass Object
(
[ArrayOfDevice] => stdClass Object
    (
        [Device] => Array
            (
                [0] => stdClass Object
                    (
                        [NamedElement] => stdClass Object
                            (
                                [Element] => stdClass Object
                                    (
                                        [ElementType] => DEVICE
                                        [id] => Device1ID
                                    )

                                [name] => Device1
                            )
                        [hostName] => Device1.hostname
                        [ipAddress] => Device1.ip
                        [location] => location1
                        [modelName] => 
                        [modelNumber] =>
                        [parentID] => xxxYYY
                        [serialNumber] => 123456789
                    )

                [1] => stdClass Object
                    (
                        [NamedElement] => stdClass Object
                            (
                                [Element] => stdClass Object
                                    (
                                        [ElementType] => DEVICE
                                        [id] => Device2ID
                                    )

                                [name] => Device2
                            )

                        [hostName] => Device2.hostname
                        [ipAddress] => Device2.ip
                        [location] => location1
                        [modelName] =>
                        [modelNumber] =>
                        [parentID] => xxxYYY
                        [serialNumber] => 987654321
                    )
            )
    )
)

...为此:

Array
(
[0] => Array
    (
        [NamedElement] => Array
            (
                [Element] => Array
                    (
                        [ElementType] => DEVICE
                        [id] => Device1ID
                    )

                [name] => Device1
            )
            [hostName] => Device1.hostname
            [ipAddress] => Device1.ip
            [location] => location1
            [modelName] => 
            [modelNumber] =>
            [parentID] => xxxYYY
            [serialNumber] => 123456789
    )

[1] => Array
    (
        [NamedElement] => Array
            (
                [Element] => Array
                    (
                        [ElementType] => DEVICE
                        [id] => Device2ID
                    )

                [name] => Device2
            )
            [hostName] => Device2.hostname
            [ipAddress] => Device2.ip
            [location] => location1
            [modelName] =>
            [modelNumber] =>
            [parentID] => xxxYYY
            [serialNumber] => 987654321
    )
)

...但我更愿意:

Array
(
[0] => Array
    (
            [ElementType] => DEVICE
            [id] => Device1ID
            [name] => Device1
            [hostName] => Device1.hostname
            [ipAddress] => Device1.ip
            [location] => location1
            [modelName] => 
            [modelNumber] =>
            [parentID] => xxxYYY
            [serialNumber] => 123456789
    )

[1] => Array
    (
            [ElementType] => DEVICE
            [id] => Device2ID
            [name] => Device2
            [hostName] => Device2.hostname
            [ipAddress] => Device2.ip
            [location] => location1
            [modelName] =>
            [modelNumber] =>
            [parentID] => xxxYYY
            [serialNumber] => 987654321
    )
)

...在退回单件商品的情况下,这:

stdClass Object
(
[ArrayOfAlarm] => stdClass Object
    (
        [Alarm] => stdClass Object
            (
                [Element] => stdClass Object
                    (
                        [ElementType] => ALARM
                        [id] => Alarm1ID
                    )

                [activeTime] => 
                [AlarmSeverity] => 
                [AlarmState] => 
                [description] => 
                [deviceID] => 
                [recommendedAction] =>
                [resolvedTime] =>
                [sensorID] => 
            )

    )

)

...为此:

Array
(
[0] => Array
    (
        [Element] => Array
            (
                [ElementType] => ALARM
                [id] => Alarm1ID
            )

        [activeTime] =>
        [AlarmSeverity] =>
        [AlarmState] =>
        [description] =>
        [deviceID] =>
        [recommendedAction] =>
        [resolvedTime] =>
        [sensorID] =>
    )
)

...但我更愿意:

Array
(
[0] => Array
    (
        [ElementType] => ALARM
        [id] => Alarm1ID
        [activeTime] =>
        [AlarmSeverity] =>
        [AlarmState] =>
        [description] =>
        [deviceID] =>
        [recommendedAction] =>
        [resolvedTime] =>
        [sensorID] =>
    )
)

您可以使用以下功能展平您的单个项目:

function flatten_item($array)
{
    $result = [];
    foreach ($array as $k => $v) {
        if (is_array($v)) {
            $result = array_merge($result, $this->flatten_item($v));
        } else {
            $result[$k] = $v;
        }
    }
    return $result;
}

当您有一组结果时,您可以将此函数作为回调传递给 array_map。仅代码的相关部分:

if (isset($v[0])) {
    $this->response = array_map([$this, 'flatten_item'], $v);
    return $this;
}
// Convert single result to an array
$this->response = [$this->flatten_item($v)];
return $this;

由于响应(到目前为止)始终具有相同的结构,您可以在不使用递归的情况下提取有效负载,这样您还可以删除 flatten 函数中的 foreach

function flatten()
{
    // Remove outer wrappers [ArrayOfX][X] by extracting the value
    $payload = current(current($this->response));
    if (isset($payload[0])) {
        $this->response = array_map([$this, 'flatten_item'], $payload);
    } else {
        $this->response = [$this->flatten_item($payload)];
    }
    return $this;
}

此处找到的函数正是您想要的,稍作修改(注释掉父键的连接):https://gist.github.com/kohnmd/11197713#gistcomment-1895523

function flattenWithKeys(array $array, $childPrefix = '.', $root = '', $result = array()) {
    foreach($array as $k => $v) {
        if(is_array($v) || is_object($v)) $result = flattenWithKeys( (array) $v, $childPrefix, $root . $k . $childPrefix, $result);
        else $result[ /*$root .*/ $k ] = $v;
    }
    return $result;
}

$object 等于您提供的对象,使用如下:

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

$result =[];             
foreach( $array['ArrayOfDevice']['Device'] as $key => $value ){
    $result[$key] = flattenWithKeys($value);
}
print_r($result);

输出:

Array
(
    [0] => Array
        (
            [ElementType] => DEVICE
            [id] => Device1ID
            [hostName] => Device1.hostname
            [ipAddress] => Device1.ip
            [location] => location1
            [modelName] => 
            [modelNumber] => 
            [parentID] => xxxYYY
            [serialNumber] => 123456789
        )

    [1] => Array
        (
            [ElementType] => DEVICE
            [id] => Device2ID
            [name] => Device2
            [hostName] => Device2.hostname
            [ipAddress] => Device2.ip
            [location] => location2
            [modelName] => 
            [modelNumber] => 
            [parentID] => xxxYYY
            [serialNumber] => 987654321
        )

)

在此处查看 运行:http://sandbox.onlinephpfunctions.com/code/851e93389b993a0e44c1e916291dc444f47047d3