Do not show the null item using the Symfony serializer.

So, I have many classes that I want to serialize using the Symfony serializer. For instance,

class Foo { public $apple = 1; public $pear = null; public function serialize() { Utils::serialize($this); } } 

which I serialize with the following call to serialize() :

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

The result gives me:

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

The expected result should be:

 <apple>1</apple> 

I took a look at the Symfony 2.8 doc and was able to find a quick solution using $normalizer->setIgnoredAttributes("pear") .

So, the improved static serialization function looks like this:

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

However, this solution does not satisfy me, since I have more complicated cases when different Foo may belong to the same class. eg

 class Bar { public $foo1; // (apple=null; pear=2) public $foo2; // (apple=2; pear=null) public function serialize() { Utils::serialize($this); } } 

Here I cannot use the setIgnoredAttributes method, since $foo1 and $foo2 do not have the same null elements. Also, I do not call the serialize method from a child class (i.e. Foo ), so setIgnoredAttributes empty.

Without writing complicated introspection code, how can I hide the default null element with Symfony 2.8 serializer? I saw, for example, that it is enabled by default with the JMSSerializer .

+5
source share
1 answer

The solution would be to extend from the ObjectNormalizer class, override the normalize() method and remove all null values ​​there:

 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); // ... 

If we have an array of Face similar to official documentation :

 // ... $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; 

The result will be those that are not null nodes:

 <?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> 
+8
source

Source: https://habr.com/ru/post/1260283/


All Articles