所以我有很多我想用Symfony序列化程序序列化的类。例如
class Foo
{
public $apple = 1;
public $pear = null;
public function serialize() {
Utils::serialize($this);
}
}
我使用以下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')
}
}
产生的输出给了我:
<apple>1</apple><pear/>
预期输出应为:
<apple>1</apple>
我查看了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);
}
}
此处我无法使用setIgnoredAttributes
方法,因为$foo1
和$foo2
没有相同的null元素。此外,我不会在此处调用子类(即serialize
)中的Foo
方法,因此setIgnoredAttributes
为空。
无需编写复杂的内省代码,如何使用Symfony 2.8序列化器默认隐藏null元素?例如,我已经看到它默认启用了JMSSerializer。
答案 0 :(得分:10)
解决方案是从ObjectNormalizer
类扩展,覆盖normalize()
方法并删除那里的所有null
值:
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);
// ...
如果我们有一个Person like the one of the 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;
结果将是那些不是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 :(得分:1)
自2016年11月以来,还有一个更好的解决方案,它具有以下功能:[Serializer] XmlEncoder : Add a way to remove empty tags
您只需要像this example那样将上下文参数remove_empty_tags
设置为true