如何在PHP中将数组转换为对象?


367

我如何将这样的数组转换为对象?

[128] => Array
    (
        [status] => Figure A.
 Facebook's horizontal scrollbars showing up on a 1024x768 screen resolution.
    )

[129] => Array
    (
        [status] => The other day at work, I had some spare time
    )

4
您想获得什么样的物体?我的意思是:属性应该是什么?
Pascal MARTIN

在一个循环中,这两个都应该是因为状态是一个数据数组,所以都应该是printet
streetparade

不确定从什么时候开始,但这$a = (object)['hello' => 'world'];
确实可行

Answers:


588

在最简单的情况下,将数组“投射”为对象可能就足够了:

$object = (object) $array;

另一种选择是将标准类实例化为变量,并在重新分配值的同时遍历数组:

$object = new stdClass();
foreach ($array as $key => $value)
{
    $object->$key = $value;
}

正如Edson Medina所指出的,一个真正干净的解决方案是使用内置json_函数:

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

这也(递归)将所有子数组转换为对象,您可能想要也可能不需要。不幸的是,与循环方法相比,它的性能下降了2-3倍。

警告!(感谢Ultra发表评论):

不同环境上的json_decode以不同的方式转换UTF-8数据。我最终在本地获得了“ 240.00”的价值,在生产中获得了“ 240”的价值-巨大的灾难。Morover如果转换失败,则将字符串get返回为NULL


41
“因为变量不能以数字开头”,是的,它们可以:$ object-> {3} ='xyz';
chelmertz

11
“具有2-3倍的性能优势”,这是不公平的比较,因为后一种方法返回递归对象,而没有更多条件的循环方法(如@streetparade的回答)仅转换第一级。
Feeela 2013年

8
@feeela我不认为这完全不公平。.我确实提到过它是递归进行转换的。同样,使用平面输入数组(不使用任何递归)可以达到2-3倍的性能
下降

6
警告!不同环境上的json_decode以不同的方式转换UTF-8数据。我最终在本地获得了“ 240.00”的价值,在生产中获得了“ 240”的价值-巨大的灾难。Morover如果转换失败,则将字符串get返回为NULL
Szymon Toda 2014年

1
请注意,在使用json_ *函数时:在这种情况下,将复制原始数组中存储的引用(例如,对其他数组的引用)。假设x阵列中的键包含对另一个阵列的引用。然后,$object->x在执行单线执行后,将复制$array['x'],不再是对原始数组的引用。在某些应用程序中这可能是无害的,但是对于较大的数组,如果稍后使用该引用,则会浪费内存并可能使执行混乱。
Coprolal

153

您可以简单地使用类型转换将数组转换为对象。

// *convert array to object* Array([id]=> 321313[username]=>shahbaz)
$object = (object) $array_name;

//now it is converted to object and you can access it.
echo $object->username;

107

简单的方法是

$object = (object)$array;

但这不是您想要的。如果您想要对象,那么您想要实现某些目标,但这是这个问题所缺少的。仅出于使用对象的原因而使用对象是没有意义的。


2
不起作用,我在问这个问题之前就做了,所以一定有另一种方法可以做
streetparade

20
为什么他必须给出想要使用对象的理由?我不认为这是有关如何,它的完成。也许他需要对它们进行json_encode或序列化?这样做可能有很多原因。
zombat

嗯。。我看着浏览器的输出看起来像这个对象(stdClass)#150(130){[0] => array(1){[“ status”] => string(130)“最后Mac和Linux用户不必觉得自己是Chrome领域中的二等公民:他们拥有正式的beta版…“}官方是一个对象,但如何迭代该方法,我可以获得像$ obj-> status这样的状态?
streetparade

zombat,无需使用JSON编码即可使用对象,json_encode()上有一个标志可使用对象。使用序列化,将需要接收者期望的特定对象类型。通常,我会尝试解决实际问题。对我来说,这个问题意味着在其他地方存在架构错误。
johannes

不错,使用laravel数组解决对象问题
Anthony Kal

105

快速破解:

// assuming $var is a multidimensional array
$obj = json_decode (json_encode ($var), FALSE);

不漂亮,但是有效。


2
我实际上很喜欢这种解决方案,使用内置函数而不是用户定义的方法总是更快,而且效果很好。谢谢你的提示。
aknatn 2012年

@Oddant解决了上面提到的问题(将数组转换为对象)。您的咆哮应该被引导到主要职位,而不是我的解决方案。
Edson Medina

@EdsonMedina我做到了,但是我的帖子太糟糕了。
vdegenne

1
@Oddant,与@EdsonMedina相同,原始问题未指定属性需要的可见性,并且由于OP $this在随后的注释中不用作访问器,因此强烈暗示他/她希望将stdClass实例作为输出,而不是用户定义的类,例如您的答案使用的类。我同意此解决方案的精巧之处,但不幸的是,这是一种非常常用的模式,可以解决嵌套数组无法转换为对象的问题。OP也有可能使用需要和对象作为输入而不是数组的接口。
DeaconDesperado 2013年

3
不要忘记,使用这种方法会丢失除基本类型以外的所有类型。例如,DateTime将是转换器stdObject。
Denis Pshenov 2014年

97

这是三种方式:

  1. 伪造真实物体:

    class convert
    {
        public $varible;
    
        public function __construct($array)
        {
            $this = $array;
        }
    
        public static function toObject($array)
        {
            $array = new convert($array);
            return $array;
        }
    }
  2. 通过将数组转换为对象将其转换为对象:

    $array = array(
        // ...
    );
    $object = (object) $array;
  3. 手动将数组转换为对象:

    $object = object;
    foreach ($arr as $key => $value) {
        $object->{$key} = $value;
    }

2
嗯,谢谢,但是您的脸部类给出以下错误致命错误:无法在第10行的/var/www/bot/inc/twitter-bot.php中重新分配$ this
streetparade

1
和typcasint @ reference不是一个好主意,即使它不能在这里工作是我得到了意外T_OBJECT_CAST,期望T_NEW或T_STRING或T_VARIABLE或'$'
streetparade

2
$ array =&(object)$ array ==很好的KISS实现!
mate64 2011年

16
为什么有人要使用不同于2)的方法?有没有缺点?
Yogu 2014年

7
将数组类型转换为对象
不适

34

简单地说,这也会为递归数组创建一个对象:

$object = json_decode(json_encode((object) $yourArray), FALSE);

4
传递falsejson_decode()会返回一个关联数组。
Rust

3
@ user3284463传递truejson_decode将返回一个关联数组,这false是默认设置,并且将返回一个StdClass实例。
艾略特·里德

23

根据需要的位置以及如何访问对象,可以使用不同的方法。

例如:只是打字

$object =  (object) $yourArray;

但是,最兼容的方法是使用一种实用程序方法(尚未成为PHP的一部分),该方法基于指定类型的字符串(或通过忽略它而只是取消引用值)来实现标准PHP强制转换:

/**
 * dereference a value and optionally setting its type
 *
 * @param mixed $mixed
 * @param null  $type (optional)
 *
 * @return mixed $mixed set as $type
 */
function rettype($mixed, $type = NULL) {
    $type === NULL || settype($mixed, $type);
    return $mixed;
}

您的案例中的用法示例(在线演示):

$yourArray = Array('status' => 'Figure A. ...');

echo rettype($yourArray, 'object')->status; // prints "Figure A. ..."

17

这个为我工作

  function array_to_obj($array, &$obj)
  {
    foreach ($array as $key => $value)
    {
      if (is_array($value))
      {
      $obj->$key = new stdClass();
      array_to_obj($value, $obj->$key);
      }
      else
      {
        $obj->$key = $value;
      }
    }
  return $obj;
  }

function arrayToObject($array)
{
 $object= new stdClass();
 return array_to_obj($array,$object);
}

用法:

$myobject = arrayToObject($array);
print_r($myobject);

返回:

    [127] => stdClass Object
        (
            [status] => Have you ever created a really great looking website design
        )

    [128] => stdClass Object
        (
            [status] => Figure A.
 Facebook's horizontal scrollbars showing up on a 1024x768 screen resolution.
        )

    [129] => stdClass Object
        (
            [status] => The other day at work, I had some spare time
        )

像往常一样,您可以像这样循环播放:

foreach($myobject as $obj)
{
  echo $obj->status;
}

但这比类型转换要慢(测试)约500%:$ obj =(对象)$ array;
xZero

@xZero,但$obj = (object) $array;不适用于多维数组。
杰夫·普基特

15

据我所知,没有内置的方法可以做到这一点,但是它就像一个简单的循环一样简单:

    $obj= new stdClass();

    foreach ($array as $k=> $v) {
        $obj->{$k} = $v;
    }

如果需要它来递归构建对象,则可以对此进行阐述。


14

您可以使用(对象)函数将数组转换为对象。

$arr= [128=> ['status'=>
                 'Figure A. Facebook \'s horizontal scrollbars showing up on a 1024x768 screen resolution.'],
                  129=>['status'=>'The other day at work, I had some spare time']];

            $ArrToObject=(object)$arr;
            var_dump($ArrToObject);

结果将是一个包含数组的对象:

object(stdClass)#1048(2){[128] => array(1){

[“ status”] =>字符串(87)“图A. Facebook的水平滚动条以1024x768的屏幕分辨率显示。}

[129] => array(1){[“状态”] => string(44)“上班的那天,我有一些空闲时间”}}


9

实际上,如果您想将此用于多维数组,则需要使用一些递归。

static public function array_to_object(array $array)
{
    foreach($array as $key => $value)
    {
        if(is_array($value))
        {
            $array[$key] = self::array_to_object($value);
        }
    }
    return (object)$array;
}

8

我一定会这样干净的方式去:

<?php

class Person {

  private $name;
  private $age;
  private $sexe;

  function __construct ($payload)
  {
     if (is_array($payload))
          $this->from_array($payload);
  }


  public function from_array($array)
  {
     foreach(get_object_vars($this) as $attrName => $attrValue)
        $this->{$attrName} = $array[$attrName];
  }

  public function say_hi ()
  {
     print "hi my name is {$this->name}";
  }
}

print_r($_POST);
$mike = new Person($_POST);
$mike->say_hi();

?>

如果您提交:

配方

你会得到这个:

麦克风

我发现比较上述来自对象的答案应该更具逻辑性,应该将它们用于制造它们的目的(封装的可爱小对象)。

另外,使用get_object_vars可以确保在可操纵对象中没有创建任何其他属性(您既不想让汽车拥有姓氏,也不希望一个人拥有四个轮子)。


为什么不使用$ attr_value代替$ array [$ attr_name]; 在yourpublic函数from_array($ array)函数中
Sakkeer Hussain'Aug

7

您还可以使用ArrayObject,例如:

<?php
    $arr = array("test",
                 array("one"=>1,"two"=>2,"three"=>3), 
                 array("one"=>1,"two"=>2,"three"=>3)
           );
    $o = new ArrayObject($arr);
    echo $o->offsetGet(2)["two"],"\n";
    foreach ($o as $key=>$val){
        if (is_array($val)) {
            foreach($val as $k => $v) {
               echo $k . ' => ' . $v,"\n";
            }
        }
        else
        {
               echo $val,"\n";
        }
    }
?>

//Output:
  2
  test
  one => 1
  two => 2
  three => 3
  one => 1
  two => 2
  three => 3

1
我认为这应该是最好的答案。更多信息,请访问:php.net/manual/en/arrayobject.construct.php
朱利安

7

我使用的一个(它是一个类成员):

const MAX_LEVEL = 5; // change it as needed

public function arrayToObject($a, $level=0)
{

    if(!is_array($a)) {
        throw new InvalidArgumentException(sprintf('Type %s cannot be cast, array expected', gettype($a)));
    }

    if($level > self::MAX_LEVEL) {
        throw new OverflowException(sprintf('%s stack overflow: %d exceeds max recursion level', __METHOD__, $level));
    }

    $o = new stdClass();
    foreach($a as $key => $value) {
        if(is_array($value)) { // convert value recursively
            $value = $this->arrayToObject($value, $level+1);
        }
        $o->{$key} = $value;
    }
    return $o;
}

7

有点复杂但易于扩展的技术:

假设你有一个数组

$a = [
     'name' => 'ankit',
     'age' => '33',
     'dob' => '1984-04-12'
];

假设您有一个Person类,该类可能具有或多或少的属性。例如

class Person 
{
    private $name;
    private $dob;
    private $age;
    private $company;
    private $city;
}

如果您仍然想将数组更改为person对象。您可以使用ArrayIterator类。

$arrayIterator = new \ArrayIterator($a); // Pass your array in the argument.

现在,您有了迭代器对象。

创建一个扩展FilterIterator类的类;您必须在其中定义抽象方法accept。根据例子

class PersonIterator extends \FilterIterator
{
    public function accept()
    {
        return property_exists('Person', parent::current());
    }
}

上面的实现仅在属性存在于类中时才绑定该属性。

在类PersonIterator中添加另一个方法

public function getObject(Person $object)
{
        foreach ($this as $key => $value)
        {
            $object->{'set' . underscoreToCamelCase($key)}($value);
        }
        return $object;
}

确保您在课堂上定义了增变子。现在,您可以在要创建对象的地方调用这些函数。

$arrayiterator = new \ArrayIterator($a);
$personIterator = new \PersonIterator($arrayiterator);

$personIterator->getObject(); // this will return your Person Object. 

6

递归是您的朋友:

function __toObject(Array $arr) {
    $obj = new stdClass();
    foreach($arr as $key=>$val) {
        if (is_array($val)) {
            $val = __toObject($val);
        }
        $obj->$key = $val;
    }

    return $obj;
}

6

这需要PHP7,因为我选择使用lambda函数来锁定主函数中的“ innerfunc”。lambda函数是递归调用的,因此需要:“ use(&$ innerfunc)”。您可以在PHP5中完成此操作,但无法隐藏innerfunc。

function convertArray2Object($defs) {
    $innerfunc = function ($a) use ( &$innerfunc ) {
       return (is_array($a)) ? (object) array_map($innerfunc, $a) : $a; 
    };
    return (object) array_map($innerfunc, $defs);
}

5

使用我做的这个功能:

function buildObject($class,$data){
    $object = new $class;
    foreach($data as $key=>$value){
        if(property_exists($class,$key)){
            $object->{'set'.ucfirst($key)}($value);
        }
    }
    return $object;
}

用法:

$myObject = buildObject('MyClassName',$myArray);

5

一支班轮

$object= json_decode(json_encode($result_array, JSON_FORCE_OBJECT));

1
注意,存储在原始数组中的引用(例如,对其他数组的引用)将通过这种单行复制。假设x阵列中的键包含对另一个阵列的引用。然后,$object->x在执行单线执行后,将复制$result_array['x'],而不是相同的数组。
Coprolal

4

简单:

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

例:

$array = array(
    'key' => array(
        'k' => 'value',
    ),
    'group' => array('a', 'b', 'c')
);

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

然后,满足以下条件:

$object->key->k === 'value';
$object->group === array('a', 'b', 'c')

1
我认为这是一种解决方法。为什么将数组编码为json然后解码呢?这对我来说不是一个最佳决定。
朱利安

1
@Julian,因为它是递归工作的,所以它以正确定义和足够可靠(“标准”)的方式进行,并且还足够快,可以很好地替代随机手工编码的猴子魔术。
Sz。


2

json_encode由于存在处理非UTF-8数据的方式,因此使用存在问题。值得注意的是,json_encode/ json_encode方法还将非关联数组保留为数组。这可能是您想要的,也可能不是。最近,我处于需要重新创建此解决方案json_功能但不使用功能的位置。这是我想出的:

/**
 * Returns true if the array has only integer keys
 */
function isArrayAssociative(array $array) {
    return (bool)count(array_filter(array_keys($array), 'is_string'));
}

/**
 * Converts an array to an object, but leaves non-associative arrays as arrays. 
 * This is the same logic that `json_decode(json_encode($arr), false)` uses.
 */
function arrayToObject(array $array, $maxDepth = 10) {
    if($maxDepth == 0) {
        return $array;
    }

    if(isArrayAssociative($array)) {
        $newObject = new \stdClass;
        foreach ($array as $key => $value) {
            if(is_array($value)) {
                $newObject->{$key} = arrayToObject($value, $maxDepth - 1);
            } else {
                $newObject->{$key} = $value;
            }
        }
        return $newObject;
    } else {

        $newArray = array();
        foreach ($array as $value) {
            if(is_array($value)) {
                $newArray[] = arrayToObject($value, $maxDepth - 1);
            } else {
                $newArray[] = $value;
            }                
        }
        return $newArray;
    }
}

2

世界上最好的方法:)

function arrayToObject($conArray)
{
    if(is_array($conArray)){
        /*
        * Return array converted to object
        * Using __FUNCTION__ (Magic constant)
        * for recursive call
        */
        return (object) array_map(__FUNCTION__, $conArray);
    }else{
        // Return object
        return $conArray;
    }
}

如果您使用其他方法,则会遇到问题。这是最好的方法。你见过


2

多维数组变成一个对象。此代码用于转换Bing搜索API的try和catch方法。

try {
        // Perform the Web request and get the JSON response
        $context = stream_context_create($options);
        $results = file_get_contents($url . "?cc=" . $country . "&category=" . $type, false, $context);
        $results = json_decode($results);
        return response()->json($results);
    } catch (\Exception $e) {
        $results = array('value' => array(
                (object) array(
                    "name" => "Unable to Retrive News",
                    "url" => "http://www.sample.com/",
                    "image" => (object) array("thumbnail" => (object) array("contentUrl" => "")),
                    "publishedAt" => "",
                    "description" => "")
            )
        );
        $results = (object) $results;
        return response()->json($results);
    }

2

您可以使用反射:

<?php

$array = ['name'=>'maria','age'=>33];

class Person {

    public $name;
    public $age;

    public function __construct(string $name, string $age){
        $this->name  = $name;
        $this->age = $age;
    }
}

function arrayToObject(array $array, string $class_name){

    $r = new ReflectionClass($class_name);
    $object = $r->newInstanceWithoutConstructor();
    $list = $r->getProperties();
    foreach($list as $prop){
      $prop->setAccessible(true);
      if(isset($array[$prop->name]))
        $prop->setValue($object, $array[$prop->name]);
    } 

    return $object;

}

$pessoa1 = arrayToObject($array, 'Person');
var_dump($pessoa1);


1

显然,这只是对其他人的答案的推断,但这是将所有覆盖维数组转换为对象的递归函数:

   function convert_array_to_object($array){
      $obj= new stdClass();
      foreach ($array as $k=> $v) {
         if (is_array($v)){
            $v = convert_array_to_object($v);   
         }
         $obj->{strtolower($k)} = $v;
      }
      return $obj;
   }

请记住,如果数组有数字键,他们仍然可以在生成的对象引用使用{}(例如:$obj->prop->{4}->prop


1

受所有这些代码的启发,我试图创建一个增强的版本,并支持以下内容:特定的类名,避免使用构造函数方法,“ beans”模式和严格模式(仅设置现有属性):

    class Util {

static function arrayToObject($array, $class = 'stdClass', $strict = false) {
        if (!is_array($array)) {
            return $array;
        }

        //create an instance of an class without calling class's constructor
        $object = unserialize(
                sprintf(
                        'O:%d:"%s":0:{}', strlen($class), $class
                )
        );

        if (is_array($array) && count($array) > 0) {
            foreach ($array as $name => $value) {
                $name = strtolower(trim($name));
                if (!empty($name)) {

                    if(method_exists($object, 'set'.$name)){
                        $object->{'set'.$name}(Util::arrayToObject($value));
                    }else{
                        if(($strict)){

                            if(property_exists($class, $name)){

                                $object->$name = Util::arrayToObject($value); 

                            }

                        }else{
                            $object->$name = Util::arrayToObject($value); 
                        }

                    }

                }
            }
            return $object;
        } else {
            return FALSE;
        }
        }
}

1

该功能与相同json_decode(json_encode($arr), false)

function arrayToObject(array $arr)
{
    $flat = array_keys($arr) === range(0, count($arr) - 1);
    $out = $flat ? [] : new \stdClass();

    foreach ($arr as $key => $value) {
        $temp = is_array($value) ? $this->arrayToObject($value) : $value;

        if ($flat) {
            $out[] = $temp;
        } else {
            $out->{$key} = $temp;
        }
    }

    return $out;
}

测试中

测试1:平面阵列

$arr = ["a", "b", "c"];
var_export(json_decode(json_encode($arr)));
var_export($this->arrayToObject($arr));

输出:

array(
    0 => 'a',
    1 => 'b',
    2 => 'c',
)
array(
    0 => 'a',
    1 => 'b',
    2 => 'c',
)

测试2:对象数组

$arr = [["a" => 1], ["a" => 1], ["a" => 1]];
var_export(json_decode(json_encode($arr)));
var_export($this->arrayToObject($arr));

输出:

array(
    0 => stdClass::__set_state(array('a' => 1,)),
    1 => stdClass::__set_state(array('a' => 1,)),
    2 => stdClass::__set_state(array('a' => 1,)),
)
array(
    0 => stdClass::__set_state(array('a' => 1,)),
    1 => stdClass::__set_state(array('a' => 1,)),
    2 => stdClass::__set_state(array('a' => 1,)),
)

测试3:对象

$arr = ["a" => 1];
var_export(json_decode($arr));
var_export($this->arrayToObject($arr));

输出:

stdClass::__set_state(array('a' => 1,))
stdClass::__set_state(array('a' => 1,))

0

我已经用非常简单的方法做到了

    $list_years         = array();
    $object             = new stdClass();

    $object->year_id   = 1 ;
    $object->year_name = 2001 ;
    $list_years[]       = $object;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.