Есть ли способ преобразовать многомерный array
в объект stdClass
в PHP?
Кастинг как (object)
не работает рекурсивно. json_decode(json_encode($array))
дает результат, который я ищу, но должен быть лучший способ …
Насколько я могу судить, для этого нет заранее подготовленного решения, поэтому вы можете просто сворачивать свои собственные:
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; }
Я знаю, что этот ответ приходит поздно, но я отправлю его всем, кто ищет решение.
Вместо всего этого цикла и т. Д. Вы можете использовать собственную функцию json_ * для PHP. У меня есть несколько удобных функций, которые я использую много
/** * 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; }
Надеюсь, это будет полезно
function toObject($array) { $obj = new stdClass(); foreach ($array as $key => $val) { $obj->$key = is_array($val) ? toObject($val) : $val; } return $obj; }
/** * 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; }
Некоторые из других решений, размещенных здесь, не могут отличить последовательные массивы (что было бы []
в JS) от карт ( {}
в JS.) Для многих случаев использования важно рассказать обо всем массивах PHP, которые имеют все последовательные цифровые ключи, которые должен быть оставлен как таковой из массивов PHP, у которых нет числовых ключей, которые должны быть преобразованы в объекты. (Мои решения ниже не определены для массивов, которые не попадают в две вышеуказанные категории.)
Метод json_decode(json_encode($x))
корректно обрабатывает два типа, но не является самым быстрым решением. Тем не менее, он по-прежнему приличный, всего 25 мкс за один проход по моим образцовым данным (усредненный в течение 1 М , минус накладные расходы цикла).
Я сравнил пару вариаций рекурсивного конвертера и получил следующее. Он восстанавливает все массивы и объекты (выполняет глубокую копию), но, кажется, быстрее, чем альтернативные решения, которые изменяют массивы на месте. Он синхронизируется с частотой 11 мкс на выполнение по моим образцовым данным:
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 мкс за выполнение:
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()
решения, используя array_walk_recursive()
Поздно, но просто хотел упомянуть, что вы можете использовать кодировку / декодирование 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
Ниже приведена функция, чтобы сделать преобразование массива в место на месте, использующее внутренний (неглубокий) внутренний механизм ввода-вывода типа «массив-объект». Он создает новые объекты только при необходимости, сводя к минимуму дублирование данных.
function toObject($array) { foreach ($array as $key=>$value) if (is_array($value)) $array[$key] = toObject($value); return (object)$array; }
Предупреждение – не используйте этот код, если существует риск иметь круглые ссылки.
Вот гладкий способ сделать это, который может обрабатывать ассоциативный массив с большой глубиной и не перезаписывать свойства объекта, которые не находятся в массиве.
<?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 );
Самое короткое, что я мог придумать:
array_walk_recursive($obj, function (&$val) { if (is_object($val)) $val = get_object_vars($val); });
Рекурсивно вы можете использовать array_map
:
public static function _arrayToObject($array) { return is_array($array) ? (object) array_map([__CLASS__, __METHOD__], $array) : $array; }
Прекрасно подходит для меня, поскольку он не отображает, например, объекты Carbon в базовый stdClass (который кодирует / декодирует json)
EDIT: эта функция представляет собой преобразование из объекта в массив.
От 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; }