2016-11-24 5 views
5

だから、Symfonyシリアライザでシリアライズしたいクラスがたくさんあります。生成される出力は私を与えるSymfonyシリアライザでヌル要素を表示しない

class Utils { 
    public static function serialize($object) { 
     $encoder = new XmlEncoder(); 
     $normalizer = new ObjectNormalizer(); 
     $serializer = new Serializer(array($normalizer), array($encoder)); 
     $str = $serializer->serialize($object, 'xml') 
    } 
} 

<apple>1</apple><pear/> 

予想される出力は次のようになります。

<apple>1</apple> 
インスタンス私は、次の serialize()呼び出しでシリアライズ

class Foo 
{ 
    public $apple = 1; 
    public $pear = null; 

    public function serialize() { 
    Utils::serialize($this); 
    } 
} 

私はSymfony 2.8 docを見て、$normalizer->setIgnoredAttributes("pear")を使って簡単な解決法を見つけました。

ので、改善されたシリアル化、静的な関数は、この

class Utils { 
    public static function ignoreNullAttributes($object) { 
    $ignored_attributes = array(); 
    foreach($object as $member => $value) { 
     if (is_null($object->$member)) { 
     array_push($ignored_attributes, $member); 
     } 
    } 
    return $ignored_attributes; 
    } 

    public static function serialize($object) { 
     $encoder = new XmlEncoder(); 
     $normalizer = new ObjectNormalizer(); 
     $normalizer->setIgnoredAttributes(Utils::ignoreNullAttributes($object)); 
     $serializer = new Serializer(array($normalizer), array($encoder)); 
     $str = $serializer->serialize($object, 'xml') 
    } 
} 

のように見える、私は別のFooは、同じクラスが所有することができ、より複雑な例を持っているのでしかし、この解決策は、私を満たしていません。例えば

class Bar 
{ 
    public $foo1; // (apple=null; pear=2) 
    public $foo2; // (apple=2; pear=null) 

    public function serialize() { 
    Utils::serialize($this); 
    } 
} 

は、ここで私は、同じnull要素を持っていない$foo1$foo2以来setIgnoredAttributesメソッドを使用することはできません。さらに、子クラス(Foo)からserializeメソッドを呼び出してsetIgnoredAttributesが空になるようにしていません。

複雑なイントロスペクションコードを書くことなく、デフォルトでSymfony 2.8シリアライザのnull要素を隠すことができますか?たとえば、デフォルトではJMSSerializerと有効になっています。我々はPerson like the one of the official documentationの配列を持っている場合

use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; 
use Symfony\Component\Serializer\Serializer; 
use Symfony\Component\Serializer\Encoder\XmlEncoder; 

class CustomObjectNormalizer extends ObjectNormalizer 
{ 
    public function normalize($object, $format = null, array $context = []) 
    { 
     $data = parent::normalize($object, $format, $context); 

     return array_filter($data, function ($value) { 
      return null !== $value; 
     }); 
    } 
} 

$encoders = array(new XmlEncoder()); 
$normalizers = array(new CustomObjectNormalizer()); 
$serializer = new Serializer($normalizers, $encoders); 

// ... 

+0

複雑なイントロスペクションcode_を書く必要はありませんが、簡単な方法はありません。恐らく、 'elseif(null === $ val){return false; } 'ここでhttps://github.com/symfony/symfony/blob/2.8/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php#L489は問題を解決しますが、これを行うには多くのコードを書き直す必要があります。ほとんどすべてのメソッドは 'XmlEncoder'にプライベートです:( – yceruto

+0

これは決して使用しませんでしたが、おそらくJMSシリアライザを使用してhttp://jmsyst.com/bundles/JMSSerializerBundleが助けてくれると助かります – Thomas

+0

@Yonelありがとう本当にありがとうsymfonyのコードで私は一人ではありません!XmlEncoderを非侵入的な方法でオーバーライドすることは可能でしょうか? – coincoin

答えて

8

溶液は、ObjectNormalizerクラスから延びるnormalize()メソッドをオーバーライドし、そこにすべてのnull値を削除することであろう

// ... 

$person1 = new Person(); 
$person1->setName('foo'); 
$person1->setAge(null); 
$person1->setSportsman(false); 

$person2 = new Person(); 
$person2->setName('bar'); 
$person2->setAge(33); 
$person2->setSportsman(null); 

$persons = array($person1, $person2); 
$xmlContent = $serializer->serialize($persons, 'xml'); 

echo $xmlContent; 

もたらしますそうでないものnullノード:

<?xml version="1.0"?> 
<response> 
    <item key="0"> 
     <name>foo</name> 
     <sportsman>0</sportsman> 
    </item> 
    <item key="1"> 
     <name>bar</name> 
     <age>33</age> 
    </item> 
</response> 
+1

これは魅力的ですこれは非常に簡単な解決策です。私は2度投票できません。ありがとうございました:) – coincoin

+2

@coincoin +1 :) –

関連する問題