【问题标题】:Add custom property to serialized object将自定义属性添加到序列化对象
【发布时间】:2014-04-08 02:00:07
【问题描述】:

我正在为 Web 服务开发 RESTful API。而且我需要暴露一些不属于实体本身的属性。

例如我有一个Pizza 实体对象,它有自己的sizename 属性。我使用 FOSRestBundleJMSSerializer 以 JSON 格式输出它。我已经为此实体设置了属性注释,以通过序列化组公开所需的属性,并且效果很好。

但是我需要添加一些不属于实体本身的属性。例如,我希望我的pizza 具有属性:isFresh,该属性由某些PizzaService::isFresh(Pizza $pizza) 服务确定。我该怎么做?

  • 我应该在序列化过程中注入一些额外的逻辑吗(如果是的话如何)?
  • 我是否应该创建一个包装实体,其中包含我想从原始实体公开的属性以及其他 external 属性?
  • 是否应该将属性isFresh 添加到原始Pizza 实体并在序列化之前填充到控制器中?
  • 是否应该返回独立于实体数据的附加数据(例如在同级 JSON 属性中)?

换句话说:围绕这个问题的最佳做法是什么?你能提供例子吗?谢谢。

【问题讨论】:

    标签: rest symfony fosrestbundle jmsserializerbundle jms-serializer


    【解决方案1】:

    我认为您可以使用 VirtualProperty 注释来做到这一点:

    /**
     * @JMS\VirtualProperty
     * @return boolean
     */
    public function isFresh (){
         ...
    }
    

    编辑:使用 Accessor 注释的另一种解决方案

    /** @Accessor(getter="getIsFresh",setter="setIsFresh") */
    private $isFresh;
    
    // ...
    public function getIsFresh()
    {
        return $this->isFresh;
    }
    
    public function setIsFresh($isFresh)
    {
        $this->isFresh= $isFresh;
    }
    

    在您的控制器中,您调用 setIsFresh 方法

    (见http://jmsyst.com/libs/serializer/master/reference/annotation

    【讨论】:

    • 这个问题也是关于这个虚拟属性依赖于服务的,似乎这只是答案的一部分。也许您也可以设想一种方法来实现它?
    • 是的,你说得对。我认为“我应该将属性 isFresh 添加到原始 Pizza 实体并在序列化之前填充到控制器中吗?”是更好的解决方案。为此,我使用 Accessor 注释添加了另一种方式
    • 您好,谢谢您的回答。为什么你认为这种方法更好?其他方法的缺点是什么?你在实践中实现过这个设计吗?
    【解决方案2】:

    我决定创建自己的类来序列化一个实体。

    示例如下:

    class PizzaSerializer implements ObjectSerializerInterface
    {
        /** @var PizzaService */
        protected $pizzaService;
    
        /**
         * @param PizzaService $pizzaService
         */
        public function __construct(PizzaService $pizzaService)
        {
            $this->pizzaService = $pizzaService;
        }
    
        /**
         * @param Pizza $pizza
         * @return array
         */
        public function serialize(Pizza $pizza)
        {
            return [
                'id'      => $pizza->getId(),
                'size'    => $pizza->getSize(),
                'name'    => $pizza->getName(),
                'isFresh' => $this->pizzaService->isFresh($pizza),
            ];
        }
    }
    

    您只需配置 DC 以将 PizzaService 注入对象序列化程序,然后从控制器中像这样调用它:

    $pizza = getPizzaFromSomewhere();
    
    $pizzaSerializer = $this->get('serializer.pizza');
    
    return $pizzaSerializer->serialize($pizza);
    

    对象序列化器将返回一个数组,该数组可以通过使用真正的序列化器轻松转换为 JSONXMLYAML 或任何其他格式喜欢JMS SerializerFOSRestBundle 会在你这样配置的情况下自动执行此操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-22
      • 2019-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-31
      • 2010-12-25
      相关资源
      最近更新 更多