有没有办法在PHP中将多维array
转换为stdClass
对象?
转换为(object)
似乎不会递归地运行。 json_decode(json_encode($array))
产生我正在寻找的结果,但必须有更好的方法......
答案 0 :(得分:55)
据我所知,没有预先构建的解决方案,所以你可以自己动手:
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;
}
答案 1 :(得分:36)
我知道这个答案迟到了,但我会把它发布给那些正在寻找解决方案的人。
而不是所有这些循环等,您可以使用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;
}
希望这会有所帮助
答案 2 :(得分:7)
function toObject($array) {
$obj = new stdClass();
foreach ($array as $key => $val) {
$obj->$key = is_array($val) ? toObject($val) : $val;
}
return $obj;
}
答案 3 :(得分: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;
}
答案 4 :(得分: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()
答案 5 :(得分:2)
您可以递归使用array_map
:
public static function _arrayToObject($array) {
return is_array($array) ? (object) array_map([__CLASS__, __METHOD__], $array) : $array;
}
对我来说非常适合,因为它没有将Carbon对象转换为基本的stdClass(json编码/解码所做的)
答案 6 :(得分:2)
public static function _arrayToObject($array) {
$json = json_encode($array);
$object = json_decode($json);
return $object
}
答案 7 :(得分:2)
将关联数组转换为对象的最简单方法是:
首先在json中对其进行编码,然后对其进行解码。
像$objectArray = json_decode(json_encode($associtiveArray));
答案 8 :(得分:1)
您和许多其他人已经指出了JSON内置函数json_decode()
和json_encode()
。您提到的方法有效,但并不完全:它不会将索引数组转换为对象,它们将保留为索引数组。但是,有一个技巧可以克服此问题。您可以使用JSON_FORCE_OBJECT
常量:
// Converts an array to an object recursively
$object = json_decode(json_encode($array, JSON_FORCE_OBJECT));
提示:此外,如here所述,您可以使用JSON函数将对象递归转换为数组:
// Converts an object to an array recursively
$array = json_decode(json_encode($object), true));
答案 9 :(得分:1)
因为提到了性能,而且实际上在很多地方它应该很重要,所以我尝试在这里回答基准功能。
您可以看到代码和示例数据 here in this gist。测试结果是使用那里存在的数据(一个随机的 JSON 文件,大小约为 200 KB),每个函数重复一千次,以便结果更准确。
以下是不同 PHP 配置的结果:
$ 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 -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 -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 函数,从而获得最佳性能,可能与您的配置无关。
答案 10 :(得分:0)
这是一个使用PHP内部(浅)数组到对象类型转换机制进行就地深度数组到对象转换的函数。 它仅在必要时创建新对象,从而最大限度地减少数据重复。
function toObject($array) {
foreach ($array as $key=>$value)
if (is_array($value))
$array[$key] = toObject($value);
return (object)$array;
}
警告 - 如果存在循环引用的风险,请不要使用此代码。
答案 11 :(得分: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;
}
答案 12 :(得分: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 );
答案 13 :(得分:0)
我能提出的最短时间:
array_walk_recursive($obj, function (&$val) { if (is_object($val)) $val = get_object_vars($val); });
答案 14 :(得分: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开始可用
答案 15 :(得分: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);
}
}
如果有人发现任何错误,请告诉我。