JMSSerializerBundle - 保留关系名称

JMSSerializerBundle - preserve relation name

我将 Symfony2 与 JMSSerializerBundle 一起使用。最后一个我是新手 =) 在这种情况下我应该怎么做:

我有图像模型。它包含一些字段,但主要字段是 "name"。另外,我有一些模型,它参考了图像模型。例如用户和应用程序。用户模型有 OneToOne 字段 "avatar",应用程序有 OneToOne 字段 "icon"。现在,我想序列化 User 实例并得到类似

的东西
{
     ...,
     "avatar": "http://example.com/my/image/path/image_name.png",
     ....
}

另外,我想序列化Application并得到

{
    ...,
    "icon": "http://example.com/my/image/path/another_image_name.png",
    ...
}

我在 User::avatar 和 Application::icon 字段上使用 @Inline 批注将图像对象(与此字段相关)减少为单个标量值(仅需要图像 "name")。此外,我的图像模型具有 ExclusionPolicy("all"),并且仅公开 "name" 字段。现在,JMSSerializer 输出是

(For User instance)
{
    ...,
    "name": "http://example.com/my/image/path/image_name.png",
    ...
}

(For Application instance)
{
    ...,
    "name": "http://example.com/my/image/path/another_image_name.png",
    ...
}

问题是:如何使 JMSSerializer 保留序列化数组中的 "avatar" 和 "icon" 键而不是 "name"?

终于,我找到了解决办法。在我看来,它不是很优雅和漂亮,但是很管用。

  1. 我告诉 JMSSerializer,User::avatar 和 Application::icon 是图像。为此,我使用了注释 @Type("Image")

    //src\AppBundle\Entity\User.php
    //...        
    /**
     * @var integer
     *
     * @ORM\OneToOne(targetEntity="AppBundle\Entity\Image")
     * @ORM\JoinColumn(name="avatar", referencedColumnName="id")
     *
     * @JMS\Expose()
     * @JMS\Type("Image")
     */
    private $avatar;
    //...
    
    //src\AppBundle\Entity\Application.php
    //...
    /**
     * @var integer
     *
     * @ORM\OneToOne(targetEntity="AppBundle\Entity\Image")
     * @ORM\JoinColumn(name="icon", referencedColumnName="id")
     *
     * @JMS\Expose()
     * @JMS\Type("Image")
     */
    private $icon;
    //...
    
  2. 我实现了处理程序,它将类型为 Image 的对象序列化为 json

    <?php
    //src\AppBundle\Serializer\ImageTypeHandler.php
    namespace AppBundle\Serializer;
    
    
    use AppBundle\Entity\Image;
    use JMS\Serializer\Context;
    use JMS\Serializer\GraphNavigator;
    use JMS\Serializer\Handler\SubscribingHandlerInterface;
    use JMS\Serializer\JsonSerializationVisitor;
    use Symfony\Component\HttpFoundation\Request;
    
    class ImageTypeHandler implements SubscribingHandlerInterface
    {
        private $request;
    
        public function __construct(Request $request) {
            $this->request = $request;
    
        }
    
        static public function getSubscribingMethods()
        {
            return [
                [
                    'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
                    'format' => 'json',
                    'type' => 'Image',
                    'method' => 'serializeImageToWebPath'
                ]
            ];
        }
    
        public function serializeImageToWebPath(JsonSerializationVisitor $visitor, Image $image = null, array $type, Context $context)
        {
            $path = $image ? "http://" . $this->request->getHost() . "/uploads/images/" . $image->getPath() : '';
    
            return $path;
        }
    }
    
  3. 最后一步是注册这个处理程序。我还注入了 request 服务以在我的处理程序中生成图像的完整 Web 路径。

    app.image_type_handler:
        class: AppBundle\Serializer\ImageTypeHandler
        arguments: ["@request"]
        scope: request
        tags:
            - { name: jms_serializer.subscribing_handler }
    

此外,您可以使用 this 变通方法来修改 post_serialize 事件中的序列化数据。