微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决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 Acme\Person();
$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>

解决方法

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

<?php

declare(strict_types=1);

namespace App\EventListener\Serializer\Entity;

use JMS\Serializer\EventDispatcher\Events;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\ObjectEvent;
use JMS\Serializer\Metadata\StaticPropertyMetadata;
use JMS\Serializer\Metadata\VirtualPropertyMetadata;
use Symfony\Component\PropertyAccess\PropertyAccessor;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\PropertyInfo\Type;
use Symfony\Component\Serializer\Encoder\XmlEncoder;

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
                    );
                }
            }
        }
    }
}
,

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

<?php

declare(strict_types=1);

namespace App\Util\Serializer\Normalizer;

use JMS\Serializer\Context;
use JMS\Serializer\GraphNavigatorInterface;
use JMS\Serializer\Handler\SubscribingHandlerInterface;
use JMS\Serializer\XmlSerializationVisitor;
use Symfony\Component\Serializer\Encoder\XmlEncoder;

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。