47

有没有办法将多维转换为PHParray中的对象?stdClass

铸造 as(object)似乎不能递归地工作。 json_decode(json_encode($array))产生我正在寻找的结果,但必须有更好的方法......

4

16 回答 16

70

据我所知,没有预先构建的解决方案,所以你可以自己动手:

function array_to_object($array) {
  $obj = new stdClass;
  foreach($array as $k => $v) {
     if(strlen($k)) {
        if(is_array($v)) {
           $obj->{$k} = array_to_object($v); //RECURSION
        } else {
           $obj->{$k} = $v;
        }
     }
  }
  return $obj;
} 
于 2011-01-25T06:03:04.853 回答
49

我知道这个答案来晚了,但我会为任何正在寻找解决方案的人发布它。

您可以使用 PHP 的原生 json_* 函数来代替所有这些循环等。我有几个我经常使用的方便的功能

/**
 * Convert an array into a stdClass()
 * 
 * @param   array   $array  The array we want to convert
 * 
 * @return  object
 */
function arrayToObject($array)
{
    // First we convert the array to a json string
    $json = json_encode($array);

    // The we convert the json string to a stdClass()
    $object = json_decode($json);

    return $object;
}


/**
 * Convert a object to an array
 * 
 * @param   object  $object The object we want to convert
 * 
 * @return  array
 */
function objectToArray($object)
{
    // First we convert the object into a json string
    $json = json_encode($object);

    // Then we convert the json string to an array
    $array = json_decode($json, true);

    return $array;
}

希望这会有所帮助

于 2012-02-07T22:59:09.040 回答
10

您和许多其他人都指出了 JSON 内置函数,json_decode()并且json_encode(). 您提到的方法有效,但并不完全:它不会将索引数组转换为对象,它们将保留为索引数组。但是,有一个技巧可以克服这个问题。您可以使用JSON_FORCE_OBJECT常量:

// Converts an array to an object recursively
$object = json_decode(json_encode($array, JSON_FORCE_OBJECT));

提示:此外,正如这里提到的,您可以使用 JSON 函数递归地将对象转换为数组:

// Converts an object to an array recursively
$array = json_decode(json_encode($object), true));    

重要提示:如果您确实关心性能,请不要使用此方法。虽然它又短又干净,但它是替代品中最慢的。请参阅我在此线程中的其他答案。

于 2019-01-06T14:37:27.297 回答
7
function toObject($array) {
    $obj = new stdClass();
    foreach ($array as $key => $val) {
        $obj->$key = is_array($val) ? toObject($val) : $val;
    }
    return $obj;
}
于 2011-08-02T08:18:10.727 回答
5

您可以array_map递归地使用:

public static function _arrayToObject($array) {
    return is_array($array) ? (object) array_map([__CLASS__, __METHOD__], $array) : $array;
}

非常适合我,因为它不会将例如 Carbon 对象转换为基本的 stdClass(json 编码/解码会这样做)

于 2017-11-11T16:28:11.843 回答
3
/**
 * Recursively converts associative arrays to stdClass while keeping integer keys subarrays as arrays
 * (lists of scalar values or collection of objects).
 */
function a2o( array $array ) {
    $resultObj = new \stdClass;
    $resultArr = array();
    $hasIntKeys = false;
    $hasStrKeys = false;
    foreach ( $array as $k => $v ) {
        if ( !$hasIntKeys ) {
            $hasIntKeys = is_int( $k );
        }
        if ( !$hasStrKeys ) {
            $hasStrKeys = is_string( $k );
        }
        if ( $hasIntKeys && $hasStrKeys ) {
            $e = new \Exception( 'Current level has both integer and string keys, thus it is impossible to keep array or convert to object' );
            $e->vars = array( 'level' => $array );
            throw $e;
        }
        if ( $hasStrKeys ) {
            $resultObj->{$k} = is_array( $v ) ? a2o( $v ) : $v;
        } else {
            $resultArr[$k] = is_array( $v ) ? a2o( $v ) : $v;
        }
    }
    return ($hasStrKeys) ? $resultObj : $resultArr;
} 
于 2014-02-08T19:23:57.207 回答
2

此处发布的其他一些解决方案无法将顺序数组([]JS 中的内容)与映射({}JS 中的内容)区分开来。对于许多用例来说,区分具有所有顺序数字键的 PHP 数组很重要,应该保留为例如,来自没有数字键的 PHP 数组,应该将其转换为对象。(对于不属于上述两类的数组,我的下面的解决方案是未定义的。)

json_decode(json_encode($x))方法确实正确处理了这两种类型,但不是最快的解决方案。尽管如此,它仍然不错,每次运行我的样本数据总共需要25µs (平均超过 1M 次运行,减去循环开销。)

我对递归转换器的几个变体进行了基准测试,最终得到以下结果。它重建所有数组和对象(执行深拷贝),但似乎比修改数组的替代解决方案更快。它在我的样本数据上每次执行的时钟为11µs :

function array_to_object($x) {
    if (!is_array($x)) {
        return $x;
    } elseif (is_numeric(key($x))) {
        return array_map(__FUNCTION__, $x);
    } else {
        return (object) array_map(__FUNCTION__, $x);
    }
}

这是一个就地版本。在一些只需要转换小部分的大型输入数据上可能会更快,但在我的示例数据上,每次执行需要15µs :

function array_to_object_inplace(&$x) {
    if (!is_array($x)) {
        return;
    }
    array_walk($x, __FUNCTION__);
    reset($x);
    if (!is_numeric(key($x))) {
        $x = (object) $x;
    }
}

我没有尝试使用解决方案array_walk_recursive()

于 2016-11-14T13:47:56.730 回答
2
public static function _arrayToObject($array) {
    $json = json_encode($array);
    $object = json_decode($json);
    return $object
}
于 2018-01-24T07:36:00.237 回答
2

将关联数组转换为对象的最简单方法是:

先用json编码,再解码。

喜欢$objectArray = json_decode(json_encode($associtiveArray));

于 2018-06-29T06:03:37.047 回答
1

因为提到了性能,实际上很多地方应该很重要,所以我尝试对这里回答的函数进行基准测试。

您可以在此 gist中查看代码和示例数据。使用那里存在的数据(一个随机的 JSON 文件,大小约为 200 KB)对结果进行测试,每个函数重复一千次,以使结果更准确。

以下是不同 PHP 配置的结果:

PHP 7.4.16(无 JIT)

$ php -dopcache.enable_cli=1 benchmark.php
pureRecursive():                        Completed in 0.000560s
pureRecursivePreservingIntKeys():       Completed in 0.000580s
jsonEncode():                           Completed in 0.002045s
jsonEncodeOptimized():                  Completed in 0.002060s
jsonEncodeForceObject():                Completed in 0.002174s
arrayMap():                             Completed in 0.000561s
arrayMapPreservingIntKeys():            Completed in 0.000592s
arrayWalkInplaceWrapper():              Completed in 0.001016s

PHP 8.0.2(无 JIT)

$ php -dopcache.enable_cli=1 benchmark.php
pureRecursive():                        Completed in 0.000535s
pureRecursivePreservingIntKeys():       Completed in 0.000578s
jsonEncode():                           Completed in 0.001991s
jsonEncodeOptimized():                  Completed in 0.001990s
jsonEncodeForceObject():                Completed in 0.002164s
arrayMap():                             Completed in 0.000579s
arrayMapPreservingIntKeys():            Completed in 0.000615s
arrayWalkInplaceWrapper():              Completed in 0.001040s

PHP 8.0.2(跟踪 JIT)

$ php -dopcache.enable_cli=1 -dopcache.jit_buffer_size=250M -dopcache.jit=tracing benchmark.php
pureRecursive():                        Completed in 0.000422s
pureRecursivePreservingIntKeys():       Completed in 0.000410s
jsonEncode():                           Completed in 0.002004s
jsonEncodeOptimized():                  Completed in 0.001997s
jsonEncodeForceObject():                Completed in 0.002094s
arrayMap():                             Completed in 0.000577s
arrayMapPreservingIntKeys():            Completed in 0.000593s
arrayWalkInplaceWrapper():              Completed in 0.001012s

如您所见,使用此基准测试最快的方法是纯递归 PHP 函数(由 @JacobRelkin 和 @DmitriySintsov 发布),尤其是在涉及 JIT 编译器时。在json_*功能方面,它们是最慢的。它们比纯方法慢大约 3 到 4 倍(在 JIT 的情况下为 5 倍),这似乎令人难以置信。

需要注意的一件事:如果您删除迭代(即每个函数只运行一次),或者甚至严格降低其计数,结果会有所不同。在这种情况下,arrayMap*()变体胜过pureRecursive*()那些(静止json_*函数方法应该是最慢的)。但是,您应该简单地忽略这些情况。在性能方面,可扩展性更为重要。

因此,在将数组转换为对象(反之亦然?)的情况下,您应该始终使用纯 PHP 函数,从而获得最佳性能,这可能与您的配置无关。

于 2021-05-22T12:48:43.657 回答
0

编辑:这个函数是从对象到数组的转换。

来自https://forrst.com/posts/PHP_Recursive_Object_to_Array_good_for_handling-0ka

protected function object_to_array($obj)
{
    $arrObj = is_object($obj) ? get_object_vars($obj) : $obj;
    foreach ($arrObj as $key => $val) {
            $val = (is_array($val) || is_object($val)) ? $this->object_to_array($val) : $val;
            $arr[$key] = $val;
    }
    return $arr;
}
于 2014-02-26T12:24:04.747 回答
0

这是一个使用 PHP 内部(浅)数组到对象类型转换机制进行就地深度数组到对象转换的函数。它仅在必要时创建新对象,从而最大限度地减少数据重复。

function toObject($array) {
    foreach ($array as $key=>$value)
        if (is_array($value))
            $array[$key] = toObject($value);
    return (object)$array;
}

警告 - 如果存在循环引用的风险,请勿使用此代码。

于 2013-01-28T14:12:30.893 回答
0

这是一种平滑的方法,可以处理具有很大深度的关联数组,并且不会覆盖不在数组中的对象属性。

    <?php

    function setPropsViaArray( $a, $o )
    {
        foreach ( $a as $k => $v )
        {
            if ( is_array( $v ) )
            {
                $o->{$k} = setPropsViaArray( $v, ! empty ( $o->{$k} ) ? $o->{$k} : new stdClass() );
            }
            else
            {
                $o->{$k} = $v;
            }
        }
        return $o;
    };

    setPropsViaArray( $newArrayData, $existingObject );
于 2016-02-22T02:55:31.913 回答
0

迟到了,但只想提一下,您可以使用 JSON 编码/解码来完全从/到数组转换:

//convert object $object into array
$array = json_decode(json_encode($object), true);
//convert array $array into object
$object = json_decode(json_encode($array));

json_encode 和 json_decode 函数从 php 5.2 开始可用

于 2017-01-17T09:28:51.270 回答
0

我一直在寻找一种方式json_decode(json_encode($array))

这里大多数其他递归函数的问题是它们还将顺序数组转换为对象。但是,默认情况下 JSON 变体不会执行此操作。它仅将关联数组转换为对象。

以下实现对我有用,就像 JSON 变体一样:

function is_array_assoc ($arr) {
    if (!is_array($arr)) return false;
    foreach (array_keys($arr) as $k => $v) if ($k !== $v) return true;
    return false;
}

// json_decode(json_encode($array))
function array_to_object ($arr) {
    if (!is_array($arr) && !is_object($arr)) return $arr;
    $arr = array_map(__FUNCTION__, (array)$arr);
    return is_array_assoc($arr) ? (object)$arr : $arr;
}

// json_decode(json_encode($array, true))
// json_decode(json_encode($array, JSON_OBJECT_AS_ARRAY))
function object_to_array ($obj) {
    if (!is_object($obj) && !is_array($obj)) return $obj;
    return array_map(__FUNCTION__, (array)$obj);
}

如果您想将功能作为一个类:

class ArrayUtils {
    public static function isArrAssoc ($arr) {
        if (!is_array($arr)) return false;
        foreach (array_keys($arr) as $k => $v) if ($k !== $v) return true;
        return false;
    }

    // json_decode(json_encode($array))
    public static function arrToObj ($arr) {
        if (!is_array($arr) && !is_object($arr)) return $arr;
        $arr = array_map([__CLASS__, __METHOD__], (array)$arr);
        return self::isArrAssoc($arr) ? (object)$arr : $arr;
    }

    // json_decode(json_encode($array, true))
    // json_decode(json_encode($array, JSON_OBJECT_AS_ARRAY))
    public static function objToArr ($obj) {
        if (!is_object($obj) && !is_array($obj)) return $obj;
        return array_map([__CLASS__, __METHOD__], (array)$obj);
    }
}

如果有人发现任何错误,请告诉我。

于 2021-03-20T13:57:45.580 回答
-1

我能想到的最短的:

array_walk_recursive($obj, function (&$val) { if (is_object($val)) $val = get_object_vars($val); });
于 2016-09-13T19:59:02.050 回答