PHPで多次元array
をオブジェクトに変換する方法はありますか?stdClass
asとしてのキャストは、(object)
再帰的に機能しないようです。 json_decode(json_encode($array))
私が探している結果を生成しますが、より良い方法が必要です...
PHPで多次元array
をオブジェクトに変換する方法はありますか?stdClass
asとしてのキャストは、(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;
}
この回答が遅れていることは承知していますが、解決策を探している人のために投稿します。
このすべてのループなどの代わりに、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;
}
これがお役に立てば幸いです
あなたや他の多くの人は、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));
重要な注意:パフォーマンスを気にする場合は、この方法を使用しないでください。短くてきれいですが、選択肢の中で最も遅いです。これに関連するこのスレッドの他の回答を参照してください。
function toObject($array) {
$obj = new stdClass();
foreach ($array as $key => $val) {
$obj->$key = is_array($val) ? toObject($val) : $val;
}
return $obj;
}
array_map
再帰的に使用できます。
public static function _arrayToObject($array) {
return is_array($array) ? (object) array_map([__CLASS__, __METHOD__], $array) : $array;
}
たとえば、Carbonオブジェクトを基本的なstdClassにキャストしないので(jsonのエンコード/デコードはキャストします)、私にとっては完璧に機能します
/**
* 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配列から。(以下の私のソリューションは、上記の2つのカテゴリに分類されないアレイに対しては定義されていません。)
このjson_decode(json_encode($x))
方法は2つのタイプを正しく処理しますが、最速のソリューションではありません。ただし、サンプルデータの実行ごとに合計25µs (100万回の実行の平均からループオーバーヘッドを差し引いたもの)で、それでもまともです。
再帰コンバーターのいくつかのバリエーションをベンチマークし、次のようになりました。すべてのアレイとオブジェクトを再構築します(ディープコピーを実行します)が、アレイを適切に変更する代替ソリューションよりも高速であるように見えます。サンプルデータでは、実行ごとに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()
public static function _arrayToObject($array) {
$json = json_encode($array);
$object = json_decode($json);
return $object
}
連想配列をオブジェクトに変換する最も簡単な方法は次のとおりです。
最初にjsonでエンコードし、次にデコードします。
お気に入り$objectArray = json_decode(json_encode($associtiveArray));
パフォーマンスが言及されており、実際には多くの場所で重要であるはずなので、ここで回答した関数のベンチマークを試みました。
この要点でコードとサンプルデータをここで見ることができます。結果は、そこに存在するデータ(ランダムなJSONファイル、サイズは約200 KB)でテストされ、結果をより正確にするために、各関数が1000回繰り返されます。
さまざまな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
ご覧のとおり、このベンチマークで最速の方法は、特にJITコンパイラーに関しては、純粋な再帰PHP関数(@JacobRelkinと@DmitriySintsovによって投稿されたもの)です。関数に関して言えばjson_*
、それらは最も遅いものです。それらは純粋な方法よりも約3倍から4倍(JITの場合は5倍)遅く、信じられないように見えるかもしれません。
注意すべき点の1つ:反復を削除する(つまり、各関数を1回だけ実行する)場合、またはその数を厳密に減らす場合でも、結果は異なります。このような場合、arrayMap*()
バリアントが優先されpureRecursive*()
ます(それでもjson_*
関数メソッドが最も遅いはずです)。ただし、これらのケースは単に無視する必要があります。パフォーマンスの観点から、スケーラビリティははるかに重要です。
その結果、配列をオブジェクトに変換する場合(およびその逆の場合)は、常に純粋なPHP関数を使用する必要があります。これにより、構成に関係なく、最高のパフォーマンスが得られます。
これは、PHPの内部(浅い)配列からオブジェクトへの型キャストメカニズムを使用して、インプレースで深い配列からオブジェクトへの変換を行う関数です。必要な場合にのみ新しいオブジェクトを作成し、データの重複を最小限に抑えます。
function toObject($array) {
foreach ($array as $key=>$value)
if (is_array($value))
$array[$key] = toObject($value);
return (object)$array;
}
警告-循環参照が発生するリスクがある場合は、このコードを使用しないでください。
編集:この関数は、オブジェクトから配列への変換です。
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;
}
これは、深い連想配列を処理でき、配列にないオブジェクトプロパティを上書きしないスムーズな方法です。
<?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 );
遅いですが、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関数は、php5.2以降で使用できます。
私は次のように振る舞う方法を探していました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);
}
}
誰かが間違いを見つけたら、私に知らせてください。
私が思いつくことができる最短:
array_walk_recursive($obj, function (&$val) { if (is_object($val)) $val = get_object_vars($val); });