2016-12-13 5 views
1

のは、我々は、ネストされたオブジェクトをシリアル化する単純なオブジェクトがあるとしましょう:JsonSerializable :: jsonSerialize()でnullプロパティを無視する方法は?

class User implements \JsonSerializable 
{ 

    private $name; 
    private $email; 
    private $address; 

    public function jsonSerialize() 
    { 
     return [ 
      'name' => $this->name, 
      'email' => $this->email, 
      'address' => $this->address 
     ]; 
    } 
} 

ネストされたオブジェクト:

class Address implements \JsonSerializable 
{ 

    private $city; 
    private $state; 

    public function jsonSerialize() 
    { 
     return [ 
      'city' => $this->city, 
      'state' => $this->state 
     ]; 
    } 
} 

我々はシリアル化するためにjson_encode()を使用し、これはネイティブJsonSerializable::jsonSerialize()を使用します。

$json = json_encode($user); 

$name$stateがnullの場合、これを取得する方法:

{ 
    "email": "[email protected]", 
    { 
     "city": "Paris" 
    } 
} 

の代わりに、この:

{ 
    "name": null, 
    "email": "[email protected]", 
    { 
     "city": "Paris", 
     "state": null 
    } 
} 
+0

自動的に行う方法はありません。シリアル化されているデータを調べ、すべてのヌル値をunset()する必要があります。それが再帰的であれば、何かarray_walkを使うことができます – Johnny

+0

再帰を管理する例を挙げられますか? – Kwadz

+0

以下の回答を参照 – Johnny

答えて

1

返された配列の周りにarray_filterをラップします。

public function jsonSerialize() 
    return array_filter([ 
     'city' => $this->city, 
     'state' => $this->state 
    ]); 
} 

これはまた、任意のNULL値が、0と偽を含む(緩く比較)偽に等しいすべてのエントリを除去します。あなたが厳格な必要がある場合、例えば。各値以上

(PHP 4> = 4.0.6、PHP 5、PHP 7)

反復処理:

function($val) { return !is_null($val); } 

array_filterのドキュメントを参照してくださいのみヌルは、次のコールバックを供給しますコールバック関数に渡します。コールバック関数がtrueを返すと、配列の現在の値が結果配列に返されます。配列キーは保持されます。

もう1つのオプションは、JSON、XML、およびYAMLの高度に設定可能なシリアライザであるJMX Serializerを使用することです。しかし、それははるかに重いです。詳細は、Exclude null properties in JMS Serializerを参照してください。

0

私のコメントはarray_walk_recursive()がそれらを値を変更することができますが、できない解除、正しくありませんでしたので、私はわずか数行のコードより、カスタム再帰関数を作りました:

<?php 

$a = (object) array(
    'first' => null, 
    'second' => 10, 
    'third' => (object) array(
    'second-first' => 100, 
    'second-second' => null, 
    'second-third' => 300 
), 
    'fourth' => 20, 
    'fifth' => null, 
    'sixth' => 10); 

function remove_null_values($a) { 
    $ret = (is_array($a) ? array() : new stdClass()); 
    foreach ($a as $k => $v) { 
    if (is_array($v) || is_object($v)) { 
     if (is_object($ret)) 
     $ret->$k = remove_null_values($v); 
     else 
     $ret[$k] = remove_null_values($v); 
    } 
    elseif (!is_null($v)) { 
     if (is_object($ret)) 
     $ret->$k = $v; 
     else 
     $ret[$k] = $v; 
    } 
    } 
    return $ret; 
} 

出力:

object(stdClass)#2 (6) { 
    ["first"]=> 
    NULL 
    ["second"]=> 
    int(10) 
    ["third"]=> 
    object(stdClass)#1 (3) { 
    ["second-first"]=> 
    int(100) 
    ["second-second"]=> 
    NULL 
    ["second-third"]=> 
    int(300) 
    } 
    ["fourth"]=> 
    int(20) 
    ["fifth"]=> 
    NULL 
    ["sixth"]=> 
    int(10) 
} 
object(stdClass)#3 (4) { 
    ["second"]=> 
    int(10) 
    ["third"]=> 
    object(stdClass)#4 (2) { 
    ["second-first"]=> 
    int(100) 
    ["second-third"]=> 
    int(300) 
    } 
    ["fourth"]=> 
    int(20) 
    ["sixth"]=> 
    int(10) 
} 

EDIT:私は、私はあなたが詳細を処理もらおう場合には、あなたはそれを考慮に些細だ配列の一部の機能を必要としない、ネストされた配列とオブジェクトの両方を動作するようにコードを更新

+0

これは配列です。それは私の質問のようなオブジェクトで動作しますか? – Kwadz

+0

はい、マイナーな変更で、ネストされたオブジェクトがありますか?サンプル入力データを提供できますか? ( 'print var_export($ x);'を実行して質問を編集する) – Johnny

+0

入れ子オブジェクトの詳細を追加しました。 – Kwadz

関連する問題