PHP - recursive Array to Object?

2019-01-23 01:04发布

问题:

Is there a way to convert a multidimensional array to a stdClass object in PHP?

Casting as (object) doesn't seem to work recursively. json_decode(json_encode($array)) produces the result I'm looking for, but there has to be a better way...

回答1:

As far as I can tell, there is no prebuilt solution for this, so you can just roll your own:

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;
} 


回答2:

I know this answer is coming late but I'll post it for anyone who's looking for a solution.

Instead of all this looping etc, you can use PHP's native json_* function. I've got a couple of handy functions that I use a lot

/**
 * 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;
}

Hope this can be helpful



回答3:

function toObject($array) {
    $obj = new stdClass();
    foreach ($array as $key => $val) {
        $obj->$key = is_array($val) ? toObject($val) : $val;
    }
    return $obj;
}


回答4:

/**
 * 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;
} 


回答5:

The simpliest way to convert an associative array to object is:

First encode it in json, then decode it.

like $objectArray = json_decode(json_encode($associtiveArray));



回答6:

Some of the other solutions posted here fail to tell apart sequential arrays (what would be [] in JS) from maps ({} in JS.) For many use cases it's important to tell apart PHP arrays that have all sequential numeric keys, which should be left as such, from PHP arrays that have no numeric keys, which should be converted to objects. (My solutions below are undefined for arrays that don't fall in the above two categories.)

The json_decode(json_encode($x)) method does handle the two types correctly, but is not the fastest solution. It's still decent though, totaling 25µs per run on my sample data (averaged over 1M runs, minus the loop overhead.)

I benchmarked a couple of variations of the recursive converter and ended up with the following. It rebuilds all arrays and objects (performing a deep copy) but seems to be faster than alternative solutions that modify the arrays in place. It clocks at 11µs per execution on my sample data:

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);
    }
}

Here is an in-place version. It may be faster on some large input data where only small parts need to be converted, but on my sample data it took 15µs per execution:

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;
    }
}

I did not try out solutions using array_walk_recursive()



回答7:

You can use the array_map recursively:

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

Works perfect for me since it doesn't cast for example Carbon objects to a basic stdClass (which the json encode/decode does)



回答8:

public static function _arrayToObject($array) {
    $json = json_encode($array);
    $object = json_decode($json);
    return $object
}


回答9:

Here's a function to do an in-place deep array-to-object conversion that uses PHP internal (shallow) array-to-object type casting mechanism. It creates new objects only when necessary, minimizing data duplication.

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

Warning - do not use this code if there is a risk of having circular references.



回答10:

Here is a smooth way to do it that can handle an associative array with great depth and doesn't overwrite object properties that are not in the 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 );


回答11:

The shortest I could come up with:

array_walk_recursive($obj, function (&$val) { if (is_object($val)) $val = get_object_vars($val); });


回答12:

Late, but just wanted to mention that you can use the JSON encoding/decoding to convert fully from/to array:

//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 and json_decode functions are available starting from php 5.2



回答13:

EDIT: This function is conversion from object to array.

From 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;
}


回答14:

You and many others have pointed to the JSON built-in functions, json_decode() and json_encode(). The method which you have mentioned works, but not completely: it won't convert indexed arrays to objects, and they will remain as indexed arrays. However, there is a trick to overcome this problem. You can use JSON_FORCE_OBJECT constant:

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

Tip: Also, as mentioned here, you can convert an object to array recursively using JSON functions:

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