Symfony Serializer上布尔属性的自定义序列化值



我使用Symfony Serializer 3.3包将对象转换为XML。

并且我希望布尔类型返回为YN,而不是10,并且我不想更改访问器方法。

下面是一个例子:

namespace Acme;
class Person
{
private $name;
private $enabled;
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
public function isEnabled()
{
return $this->enabled;
}
public function setEnabled($enabled)
{
$this->enabled = $enabled;
}
}
$person = new AcmePerson();
$person->setName('foo');
$person->setEnabled(true);
$serializer->serialize($person, 'xml');

得到结果:

<?xml version="1.0"?>
<response>
<name>foo</name>
<enabled>1</enabled> <!-- bad value -->
</response>

预期的结果:

<?xml version="1.0"?>
<response>
<name>foo</name>
<enabled>Y</enabled>  <!-- goodvalue -->
</response>

您可以注册一个新的jms类型formatted_boolean

<?php
declare(strict_types=1);
namespace AppUtilSerializerNormalizer;
use JMSSerializerContext;
use JMSSerializerGraphNavigatorInterface;
use JMSSerializerHandlerSubscribingHandlerInterface;
use JMSSerializerXmlSerializationVisitor;
use SymfonyComponentSerializerEncoderXmlEncoder;
class BoolHandler implements SubscribingHandlerInterface
{
public static function getSubscribingMethods(): array
{
return [
[
'direction' => GraphNavigatorInterface::DIRECTION_SERIALIZATION,
'format'    => XmlEncoder::FORMAT,
'type'      => 'formatted_boolean',
'method'    => 'serializeToXml',
],
];
}
public function serializeToXml(
XmlSerializationVisitor $visitor,
$value,
array $type,
Context $context = null
) {
return $value ? 'Y' : 'N';
}
}

但是在这种情况下,您必须为每个布尔属性添加@JMSType(name="formatted_boolean")

您可以通过事件订阅者完成此操作。它影响所有布尔属性

<?php
declare(strict_types=1);
namespace AppEventListenerSerializerEntity;
use JMSSerializerEventDispatcherEvents;
use JMSSerializerEventDispatcherEventSubscriberInterface;
use JMSSerializerEventDispatcherObjectEvent;
use JMSSerializerMetadataStaticPropertyMetadata;
use JMSSerializerMetadataVirtualPropertyMetadata;
use SymfonyComponentPropertyAccessPropertyAccessor;
use SymfonyComponentPropertyInfoExtractorReflectionExtractor;
use SymfonyComponentPropertyInfoType;
use SymfonyComponentSerializerEncoderXmlEncoder;
class BoolSubscriber implements EventSubscriberInterface
{
/**
* @return array<array<string, mixed>>
*/
public static function getSubscribedEvents(): array
{
return [
[
'event'    => Events::POST_SERIALIZE,
'method'   => 'onPostSerialize',
'format'   => XmlEncoder::FORMAT,
'priority' => 0,
],
];
}
public function onPostSerialize(ObjectEvent $event): void
{
$visitor = $event->getVisitor();
$class = get_class($event->getObject());
$reflectionExtractor = new ReflectionExtractor();
$properties          = $reflectionExtractor->getProperties($class);
$propertyAccessor = new PropertyAccessor();
foreach ($properties as $property) {
$types = $reflectionExtractor->getTypes($class, $property);
$type = $types[0] ?? null;
if ($type instanceof Type && $type->getBuiltinType() == Type::BUILTIN_TYPE_BOOL) {
$metadata = new VirtualPropertyMetadata($class, $property);
if ($visitor->hasData($metadata->name)) {
$value = $propertyAccessor->getValue($event->getObject(), $property) ? 'Y' : 'N';
$visitor->visitProperty(
new StaticPropertyMetadata($class, $metadata->name, $value),
$value
);
}
}
}
}
}

最新更新